Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
424 views
in Technique[技术] by (71.8m points)

r - arrange_() multiple columns with descending order

I am trying to use arrange_() with string input and in one of the columns in descending order.

library(dplyr) # R version 3.3.0 (2016-05-03) , dplyr_0.4.3 
# data
set.seed(1)
df1 <- data.frame(grp = factor(c(1,2,1,2,1)),
                  x = round(runif(5,1,10), 2))

#   grp    x
# 1   1 3.39
# 2   2 4.35
# 3   1 6.16
# 4   2 9.17
# 5   1 2.82

Below is what I need to achieve:

df1 %>% arrange(grp, -x)
df1 %>% arrange(grp, desc(x))
#   grp    x
# 1   1 6.16
# 2   1 3.39
# 3   1 2.82
# 4   2 9.17
# 5   2 4.35

In my case second column is a string:

#dynamic string
myCol <- "x"

#failed attempts
df1 %>% arrange_("grp", desc(myCol))

Error: incorrect size (1), expecting : 5

df1 %>% arrange_("grp", "desc(myCol)")

Error: object 'myCol' not found

df1 %>% arrange_(c("grp", "desc(myCol)"))
#wrong output
#   grp    x
# 1   1 3.39
# 2   1 6.16
# 3   1 2.82
# 4   2 4.35
# 5   2 9.17

I found similar solution here, but couldn't make it work:

df1 %>% arrange_(.dots = c("grp", "desc(myCol)"))

Error: object 'myCol' not found

Feels like I am missing something very obvious, ideas?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

We can paste 'desc' as a string to evaluate it.

myCol1 <- paste0("desc(", "x)")
df1 %>% 
     arrange_(.dots = c("grp", myCol1))
#  grp    x
#1   1 6.16
#2   1 3.39
#3   1 2.82
#4   2 9.17
#5   2 4.35

Or with 'myCol'

df1 %>% 
      arrange_(.dots = c("grp", paste0("desc(", myCol, ")")))

Or use lazyeval

library(lazyeval)
df1 %>%
     arrange_(.dots = c("grp", interp(~ desc(n1), n1 = as.name(myCol))))
#  grp    x
#1   1 6.16
#2   1 3.39
#3   1 2.82
#4   2 9.17
#5   2 4.35

By using "desc(myCol)", it is a single string and the value of the 'myCol' is not evaluated.

Update

Or another option is parse_expr (from rlang) and evaluate with !!

df1 %>%
    arrange(grp, !! rlang::parse_expr(myCol1))
#grp    x
#1   1 6.16
#2   1 3.39
#3   1 2.82
#4   2 9.17
#5   2 4.35

Or using the original string in the OP's post. Convert the string to symbol (sym), evaluate (!!) and arrange it in descending (desc) order

myCol <- "x"
df1 %>% 
    arrange(grp, desc(!! rlang::sym(myCol)))
# grp    x
#1   1 6.16
#2   1 3.39
#3   1 2.82
#4   2 9.17
#5   2 4.35




 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...