在dplyr 0.7.0+中正确使用dplyr :: select,使用字符向量选择列

时间:2017-06-24 18:52:48

标签: r dplyr tidyverse rlang tidyeval

假设我们有一个字符向量cols_to_select,其中包含我们要从数据框df中选择的一些列,例如

df <- tibble::data_frame(a=1:3, b=1:3, c=1:3, d=1:3, e=1:3)
cols_to_select <- c("b", "d")

假设我们也想使用dplyr::select,因为它是使用%>%的操作的一部分,因此使用select可以使代码易于阅读。

似乎有很多方法可以实现,但有些方法比其他方法更强大。请你告诉我哪个是正确的&#39;版本和为什么?或许还有另一个更好的方法?

dplyr::select(df, cols_to_select) #Fails if 'cols_to_select' happens to be the name of a column in df 
dplyr::select(df, !!cols_to_select) # i.e. using UQ()
dplyr::select(df, !!!cols_to_select) # i.e. using UQS()

cols_to_select_syms <- rlang::syms(c("b", "d"))  #See [here](https://stackoverflow.com/questions/44656993/how-to-pass-a-named-vector-to-dplyrselect-using-quosures/44657171#44657171)
dplyr::select(df, !!!cols_to_select_syms)

P.S。我意识到这可以使用简单的df[,cols_to_select]

在基础R中实现

1 个答案:

答案 0 :(得分:6)

https://cran.r-project.org/web/packages/rlang/vignettes/tidy-evaluation.html中的dplyr::select使用了一个示例:

dplyr::select(df, !!cols_to_select)

为什么呢?让我们探讨您提到的选项:

选项1

dplyr::select(df, cols_to_select)

如你所说,如果cols_to_select恰好是df中列的名称,则会失败,所以这是错误的。

选项4

cols_to_select_syms <- rlang::syms(c("b", "d"))  
dplyr::select(df, !!!cols_to_select_syms)

这看起来比其他解决方案更复杂。

选项2和3

dplyr::select(df, !!cols_to_select)
dplyr::select(df, !!!cols_to_select)

这两种解决方案在这种情况下提供相同的结果。您可以通过执行以下操作查看!!cols_to_select!!!cols_to_select的输出:

dput(rlang::`!!`(cols_to_select)) # c("b", "d")
dput(rlang::`!!!`(cols_to_select)) # pairlist("b", "d")

!!UQ()运算符会立即在其上下文中计算其参数,这就是您想要的。

!!!UQS()运算符用于一次将多个参数传递给函数。

对于您的示例中的字符列名称,如果将它们作为长度为2的单个向量(使用!!)或作为具有两个长度为1的向量的列表(使用{{1}),则无关紧要})。对于更复杂的用例,您需要使用多个参数作为列表:(使用!!!

!!!