【问题标题】:Correct usage of dplyr::select in dplyr 0.7.0+, selecting columns using character vector在 dplyr 0.7.0+ 中正确使用 dplyr::select,使用字符向量选择列
【发布时间】:2017-11-28 02:55:50
【问题描述】:

假设我们有一个字符向量 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,因为它是使用%&gt;% 的操作的一部分,所以使用select 使代码易于阅读。

似乎有多种方法可以实现这一目标,但有些方法比其他方法更强大。请你能告诉我哪个是“正确”的版本,为什么?或者也许还有其他更好的方法?

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)

附言我意识到这可以在基础 R 中使用 df[,cols_to_select]

来实现

【问题讨论】:

  • 作为替代使用 .vars 参数:select_at(df, .vars = cols_to_select)

标签: r dplyr tidyverse rlang tidyeval


【解决方案1】:

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 的向量的列表(使用 !!!)给出都没有关系。对于更复杂的用例,您需要使用多个参数作为列表:(使用!!!

a <- quos(contains("c"), dplyr::starts_with("b"))
dplyr::select(df, !!a) # does not work
dplyr::select(df, !!!a) # does work

【讨论】:

  • 谢谢你,这个答案非常好 - 很高兴澄清为什么 !!!!! 解决方案都有效,并且 dput/rlang 示例很好地帮助我解决了这样的问题未来
猜你喜欢
  • 2018-09-09
  • 1970-01-01
  • 2021-11-24
  • 2016-10-31
  • 2018-05-26
  • 2020-08-29
  • 1970-01-01
相关资源
最近更新 更多