Reputation: 143
I need to sort a data frame by several columns, and I have the name of the columns in a variable. My question is related to this one but in my case the columns to be used to sort are stored in a variable, like in this other question.
I borrow the data frame from the first question:
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"),
levels = c("Low", "Med", "Hi"), ordered = TRUE),
x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
z = c(1, 1, 1, 2))
dd
b x y z
1 Hi A 8 1
2 Med D 3 1
3 Hi A 9 1
4 Low C 9 2
What I need to do is sort dd
by z
decreasing, and by b
increasing.
The sort answer is:
dd[with(dd, order(-z, b)), ]
What I have is:
sort_list <- c("z","b")
From the second question I know I can do:
dd[do.call(order, dd[, sort_list]),]
But that only gives me increasing order for both variables. What I can't figure out is how to do it with decreasing order. I've tried this:
dd[do.call(order, list(dd[, sort_list]), decreasing = c(TRUE,FALSE)),]
which produces an error, because it's assuming the decreasing
argument is just another ordering item.
Upvotes: 3
Views: 124
Reputation: 7871
dplyr
example
library(dplyr)
sort_list <- c("z","b")
sort_order=c(TRUE,FALSE)
dd %>% arrange_(.dots=ifelse(sort_order,paste0("desc(",sort_list,")"),sort_list))
Upvotes: 0
Reputation: 6552
Using data.table
order function, you could do :
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"),
levels = c("Low", "Med", "Hi"), ordered = TRUE),
x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
z = c(1, 1, 1, 2))
library(data.table)
sort_list <- c("z","b")
sort_order <- c(-1, 1)
setDT(dd)
setorderv(dd, sort_list, sort_order)
dd
#> b x y z
#> 1: Low C 9 2
#> 2: Med D 3 1
#> 3: Hi A 8 1
#> 4: Hi A 9 1
Upvotes: 2
Reputation: 5691
This works:
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"),
levels = c("Low", "Med", "Hi"), ordered = TRUE),
x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
z = c(1, 1, 1, 2))
sort_list <- c("z","b")
dd[order(-dd[,sort_list[1]], dd[,sort_list[2]]), ]
# or
dd[order(-dd[,sort_list["z"]], dd[,sort_list["b"]]), ]
if that's annoying to type, or the variable names change, or whatever, you could stick it in a function (in right order):
downup <- function(dat, sort_list){
dat[order(-dat[,sort_list[1]], dat[,sort_list[2]]), ]
}
downup(dd)
That help?
Upvotes: 1