在 `dplyr` 动词中使用不带引号的字符串:`select` 和 `arrange` 的工作方式不同

Using unquoted strings in with `dplyr` verbs: `select` and `arrange` working differently

我正在尝试取消引用一个字符串以供在 dplyr::arrange 中使用。它似乎不起作用。但是,它似乎在 dplyr::select 中可以正常工作。 我是不是遗漏了什么或做错了什么?


library(tidyverse)

df <- tibble(x = c(1, 2, 3),
             y = c(8, 6, 3))

v <- 'y'

# `select` works with `!!v` 

df %>% select(y)
#> # A tibble: 3 x 1
#>       y
#>   <dbl>
#> 1     8
#> 2     6
#> 3     3

df %>% select(!!v)
#> # A tibble: 3 x 1
#>       y
#>   <dbl>
#> 1     8
#> 2     6
#> 3     3

# `arrange` not work with `!!v`

df %>% arrange(y)
#> # A tibble: 3 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1     3     3
#> 2     2     6
#> 3     1     8

df %>% arrange(!!v)
#> # A tibble: 3 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1     1     8
#> 2     2     6
#> 3     3     3

您需要先将字符串转换为变量(使用 sym()),然后在 arrange().

中取消引用
df %>% arrange(!!sym(v))

#> # A tibble: 3 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1     3     3
#> 2     2     6
#> 3     1     8

select()可以直接接受字符串输入,但不推荐

df %>% select(v)

#> Note: Using an external vector in selections is ambiguous.
#> i Use `all_of(v)` instead of `v` to silence this message.
#> i See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
#> This message is displayed once per session.
#> # A tibble: 3 x 1
#>       y
#>   <dbl>
#> 1     8
#> 2     6
#> 3     3

reprex package (v0.3.0)

于 2020-11-21 创建

在 selecting 动词中,使用 all_of()any_of()。如果不是所有变量都存在于数据框中,前者会导致错误,后者是宽松的(并且通常对 deselecting 更有用)

df %>% select(all_of(v))
#> # A tibble: 3 x 1
#>       y
#>   <dbl>
#> 1     8
#> 2     6
#> 3     3

在动作动词中,例如 arrange()mutate(),select 单个变量通过子代化 .data 代词:

df %>% arrange(.data[[v]])
#> # A tibble: 3 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1     3     3
#> 2     2     6
#> 3     1     8

您还可以通过使用 across():

在动作动词中使用 selection
df %>% arrange(across(starts_with("y")))
#> # A tibble: 3 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1     3     3
#> 2     2     6
#> 3     1     8

这意味着您也可以使用 all_of() 以及来自字符向量的 select:

df %>% arrange(across(all_of(v)))
#> # A tibble: 3 x 2
#>       x     y
#>   <dbl> <dbl>
#> 1     3     3
#> 2     2     6
#> 3     1     8