将变量名称的向量传递给dplyr中的arrange()

rso*_*ren 32 sorting r parameter-passing dplyr

我想传递arrange(){dplyr}一个变量名的向量来排序.通常我只需输入我想要的变量,但我正在尝试创建一个函数,其中排序变量可以作为函数参数输入.

df <- structure(list(var1 = c(1L, 2L, 2L, 3L, 1L, 1L, 3L, 2L, 4L, 4L
  ), var2 = structure(c(10L, 1L, 8L, 3L, 5L, 4L, 7L, 9L, 2L, 6L
  ), .Label = c("b", "c", "f", "h", "i", "o", "s", "t", "w", "x"
  ), class = "factor"), var3 = c(7L, 5L, 5L, 8L, 5L, 8L, 6L, 7L, 
  5L, 8L), var4 = structure(c(8L, 5L, 1L, 4L, 7L, 4L, 3L, 6L, 9L, 
  2L), .Label = c("b", "c", "d", "e", "f", "h", "i", "w", "y"), 
  class = "factor")), .Names = c("var1", "var2", "var3", "var4"), 
  row.names = c(NA, -10L), class = "data.frame")

# this is the normal way to arrange df with dplyr
df %>% arrange(var3, var4)

# but none of these (below) work for passing a vector of variables
vector_of_vars <- c("var3", "var4")
df %>% arrange(vector_of_vars)
df %>% arrange(get(vector_of_vars))
df %>% arrange(eval(parse(text = paste(vector_of_vars, collapse = ", "))))
Run Code Online (Sandbox Code Playgroud)

far*_*nsy 32

哈德利并没有在帮助档案中明白这一点 - 只是在他的NSE小插图中.下划线后面的函数版本使用标准评估,因此您可以传递它们的字符串向量等.

如果我正确理解您的问题,您只需更换arrange(),arrange_()它就会起作用.

具体来说,.dots当你这样做时,传递字符串向量作为参数.

> df %>% arrange_(.dots=c("var1","var3"))
   var1 var2 var3 var4
1     1    i    5    i
2     1    x    7    w
3     1    h    8    e
4     2    b    5    f
5     2    t    5    b
6     2    w    7    h
7     3    s    6    d
8     3    f    8    e
9     4    c    5    y
10    4    o    8    c
Run Code Online (Sandbox Code Playgroud)

========== 2018年3月更新==============

如我在此处所示,使用dplyr中的标准评估版本现在被视为已弃用.您可以通过新方式阅读Hadley的编程插图.基本上,您将使用!!取消引用一个变量或!!!取消引用内部变量的向量arrange().

当您传递这些列时,如果它们是裸的,则使用quo()一个变量或quos()向量引用它们.不要使用引号.请参阅Akrun的答案.

如果您的列已经是字符串,则使用rlang::sym()单个列或rlang::syms()向量使用它们的名称.请参阅Christos的答案.您也可以使用as.name()单个列.不幸的是,在撰写本文时,关于如何使用的信息rlang::sym()还没有成为我上面链接的插图(最终将根据他的草案在"可变参数quasiquotation"一节中).

  • 啊,这有效:````df%>%安排_(.dots = vector_of_vars)```.farnsy,如果你做出这个改变,我会给你答案 (5认同)
  • `vector_of_vars < - c("desc(var3)","var4"); df%>%arrange _(.dots = vector_of_vars)` (5认同)
  • 我也在考虑这个问题,但如果你做'df%>%arrange_(vector_of_vars)`,它似乎忽略了第二个元素并仅对第一个元素进行排序.但是,如果你执行'df%>%arrange_(vector_of_vars [1],vector_of_vars [2])`,那么它会对这两个值进行排序.我假设有一种比第二种方法更优雅的方法,但我不确定它是什么. (2认同)
  • @farnsy如果你想按降序排序怎么办?如何传递desc参数?我还没搞清楚! (2认同)

akr*_*run 16

在新版本中(即将推出0.6.0dplyr),我们可以利用的quosures

library(dplyr)
vector_of_vars <- quos(var1, var3)
df %>%
    arrange(!!! vector_of_vars)
#   var1 var2 var3 var4
#1     1    i    5    i
#2     1    x    7    w
#3     1    h    8    e
#4     2    b    5    f
#5     2    t    5    b
#6     2    w    7    h
#7     3    s    6    d
#8     3    f    8    e
#9     4    c    5    y
#10    4    o    8    c
Run Code Online (Sandbox Code Playgroud)

当有多个变量时,我们使用quos和单个变量quo.该quos会返回一个list引用变量和内部arrange,我们解除引用的list使用!!!进行评估

  • ...现在又被弃用了...`1:用'!!!'取消引用语言对象 从 rlang 0.3.0 开始软弃用。请用 '!!' 相反。`令人惊讶(保持礼貌)有多少函数在 tidyverse 中不断被弃用......我认为我将回到 Base R 以获得我的长期代码...... (7认同)

Chr*_*tos 13

在quosures精神:

df %>% arrange(!!! rlang::syms(c("var1", "var3")))
Run Code Online (Sandbox Code Playgroud)

对于单个变量,它看起来像:

df %>% arrange(!! rlang::sym(c("var1")))
Run Code Online (Sandbox Code Playgroud)


Cec*_*Lee 10

我想现在你可以使用dplyr::arrange_at().

library(dplyr)

### original
head(iris)
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          5.1         3.5          1.4         0.2  setosa
# 2          4.9         3.0          1.4         0.2  setosa
# 3          4.7         3.2          1.3         0.2  setosa
# 4          4.6         3.1          1.5         0.2  setosa
# 5          5.0         3.6          1.4         0.2  setosa
# 6          5.4         3.9          1.7         0.4  setosa

### arranged
iris %>% 
  arrange_at(c("Sepal.Length", "Sepal.Width")) %>% 
  head()
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          4.3         3.0          1.1         0.1  setosa
# 2          4.4         2.9          1.4         0.2  setosa
# 3          4.4         3.0          1.3         0.2  setosa
# 4          4.4         3.2          1.3         0.2  setosa
# 5          4.5         2.3          1.3         0.3  setosa
# 6          4.6         3.1          1.5         0.2  setosa
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用。天哪,多年来对于如此基本的东西有如此多的语法变化。 (2认同)