dplyr arrange() 在 c() 内部使用单个变量,但在函数内部评估时不适用于 c() 内部的多个变量

dplyr arrange() works with single variable inside c(), but not multiple variables inside of c() when evaluated inside of a function

我在网上可以找到的关于 tidyeval 的所有信息要么较旧,要么不是最新版本 tidyverse\dplyr 的最新版本,要么不太适用。

一个例子是:

df <- tribble(
       ~var1, ~var2, ~var3,
         1,     2,     3,
         4,     5,     6,
         7,     8,     9
        )

我写了一个小函数:

fun <- function(data, select_var, arrange_var) {
   select_var <- enquo(select_var)
   arrange_var <- enquo(arrange_var)

   data %>%
     select(!!select_var) %>%
     arrange(!!arrange_var)
   }

该函数只是选择列,然后按行排列。

当我将参数传递给函数时,它可以很好地处理 c() 中的单个变量:

fun(df, 
    c(var1,
      var2)),
    c(var2))

但是,当我尝试将两个变量传递给它时:

    fun(df, 
    c(var1,
      var2)),
    c(var1,
      var2))

我收到以下错误:

Error: incorrect size (282) at position 1, expecting : 141

我能找到的最接近的堆栈响应是: Pass a vector of variable names to arrange() in dplyr

但这两个似乎都给出了包含已弃用解决方案的答案(例如,arrange_())

这里有一些重要信息: tidyeval resource roundup 作者:玛拉·埃弗里克

Separating and Trimming Messy Data the Tidy Way 作者:保罗·奥尔德姆

当然我已经深入研究:tidyeval

然而 none 他们似乎解决了这个问题。花了一个下午后,我已经用尽了我的资源。该代码可以在标准 R 文件中找到,只是无法让它在函数内部工作,但准备放弃,所以我想看看你们这些好心人是否可以提供帮助。提前致谢。

更新 2022/03/17

tidyverse 已经发展,这个答案也应该如此。

不需要enquo了!相反,我们将 tidy-select 表达式括在双大括号 {{ }}.

library("tidyverse")

df <- tribble(
  ~var1, ~var2, ~var3,
  1, 2, 3,
  4, 5, 6,
  7, 8, 9
)

fun <- function(data, select_vars, ...) {
  data %>%
    select(
      {{ select_vars }}
    ) %>%
    arrange(
      ...
    )
}


fun(df, c(var1, var2), desc(var2))
#> # A tibble: 3 × 2
#>    var1  var2
#>   <dbl> <dbl>
#> 1     7     8
#> 2     4     5
#> 3     1     2
fun(df, c(var1, var2), var1, var2)
#> # A tibble: 3 × 2
#>    var1  var2
#>   <dbl> <dbl>
#> 1     1     2
#> 2     4     5
#> 3     7     8

我们仍然不能将 c()arrangefilter 动词一起使用,因为 data-masking.

不允许这样做
df %>%
  arrange(
    c(var1, var2)
  )
#> Error in `arrange()`:
#> ! Problem with the implicit `transmute()` step.
#> x Problem while computing `..1 = c(var1, var2)`.
#> x `..1` must be size 3 or 1, not 6.

reprex package (v2.0.1)

于 2022-03-17 创建

旧答案

arrange_var 替换为 ... 并指定变量而不将它们包含在 c() 中使其工作。

library("dplyr")

df <- tribble(
  ~var1, ~var2, ~var3,
  1, 2, 3,
  4, 5, 6,
  7, 8, 9
)

fun <- function(data, select_var, ...) {
  select_var <- enquo(select_var)
  data %>%
    select(!!select_var) %>%
    # You can pass the dots to `arrange` directly
    arrange(...)
}

fun(df, c(var1, var2), var2)
#> # A tibble: 3 x 2
#>    var1  var2
#>   <dbl> <dbl>
#> 1     1     2
#> 2     4     5
#> 3     7     8
fun(df, c(var1, var2), var1, var2)
#> # A tibble: 3 x 2
#>    var1  var2
#>   <dbl> <dbl>
#> 1     1     2
#> 2     4     5
#> 3     7     8

reprex package (v0.2.1)

于 2019-03-08 创建

原来只有select支持字符串和字符向量。正如文档所说,“这与其他字符串不明确的动词不同。” 请参阅 dplyr::select 的最后一个示例。

# Two alternatives; both work with `select`.
df %>%
  select(var1, var2)
#> # A tibble: 3 x 2
#>    var1  var2
#>   <dbl> <dbl>
#> 1     1     2
#> 2     4     5
#> 3     7     8
df %>%
  select(c(var1, var2))
#> # A tibble: 3 x 2
#>    var1  var2
#>   <dbl> <dbl>
#> 1     1     2
#> 2     4     5
#> 3     7     8

# `arrange` only works with lists on comma separated unquoted variable names.
df %>%
  arrange(var1, var2)
#> # A tibble: 3 x 3
#>    var1  var2  var3
#>   <dbl> <dbl> <dbl>
#> 1     1     2     3
#> 2     4     5     6
#> 3     7     8     9
df %>%
  arrange(c(var, var2))
#> Error: incorrect size (4) at position 1, expecting : 3

reprex package (v0.2.1)

于 2019-03-08 创建