I think that your example was potentially an 'easy case' because there were as many negatives as positives, so the equal length would mean you could trivially cbind the two parts together.
However, with unequal parts as in my example, you would need a cbind that pads, I modified such a function to operate by converting to character and padding with blank string.
library(dplyr)
#credit https://gist.github.com/abelsonlive/4112423
cbind.fill<-function(...){
nm <- list(...)
nm<-lapply(nm, as.matrix)
n <- max(sapply(nm, nrow))
r1<- do.call(cbind, lapply(nm, function (x)
rbind(x, matrix("", n-nrow(x), ncol(x)))))
r2 <-as.data.frame(r1)
}
df <- data.frame(
A = c("2","-4","5","-9", -2 ),
B = c(1,3,2,3,1))
df <- mutate_all(df,
as.numeric) %>%
arrange(desc(A))
(r1 <- cbind.fill(filter(df,A>0)
,filter(df,A<=0)))