如何使用字符串为 dplyr::arrange 指定带有 desc() 的排序变量?

How to specify sorting variable with desc() for dplyr::arrange using string?

以下代码应按降序对列 hp 进行排序,但它失败了。

有人可以指出问题吗?

data(mtcars)
result = dplyr::arrange( mtcars, !! rlang::expr("desc(hp)") )
head(result)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

补充说明

使用 str2lang() 代替 rlang::expr() 效果很好。有人能解释一下原因吗?

data(mtcars)
result = dplyr::arrange( mtcars, !! str2lang("desc(hp)") )
                     mpg cyl disp  hp drat    wt  qsec vs am gear carb
Maserati Bora       15.0   8  301 335 3.54 3.570 14.60  0  1    5    8
Ford Pantera L      15.8   8  351 264 4.22 3.170 14.50  0  1    5    4
Duster 360          14.3   8  360 245 3.21 3.570 15.84  0  0    3    4
Camaro Z28          13.3   8  350 245 3.73 3.840 15.41  0  0    3    4
Chrysler Imperial   14.7   8  440 230 3.23 5.345 17.42  0  0    3    4
Lincoln Continental 10.4   8  460 215 3.00 5.424 17.82  0  0    3    4

这是我的误会

我应该使用的是rlang::parse_expr(),而不是rlang::expr()。以下代码有效。

data(mtcars)
result = dplyr::arrange( mtcars, !! rlang::parse_expr("desc(hp)") )

要说明问题,我们需要看看rlang::expr是做什么的。 它捕获一个表达式而不对其求值。所以当你写 rlang::expr("desc(hp)") 结果实际上是一个字符串:

# setup:
mtcars <- dplyr::as_tibble(mtcars)

eval(rlang::expr("desc(hp)"))
#> [1] "desc(hp)"

这与以下无异:

dplyr::arrange(mtcars, "desc(hp)")
#> # A tibble: 32 x 11
#>      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1  21       6  160    110  3.9   2.62  16.5     0     1     4     4
#>  2  21       6  160    110  3.9   2.88  17.0     0     1     4     4
#>  3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
#>  4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
#>  5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
#>  6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
#>  7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#>  8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
#>  9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
#> 10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
#> # ... with 22 more rows

要真正让它与 rlang::expr 一起工作,我们需要使用实际的表达式而不是字符串作为参数:

dplyr::arrange(mtcars, !! rlang::expr(desc(hp)))
#> # A tibble: 32 x 11
#>      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1  15       8  301    335  3.54  3.57  14.6     0     1     5     8
#>  2  15.8     8  351    264  4.22  3.17  14.5     0     1     5     4
#>  3  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#>  4  13.3     8  350    245  3.73  3.84  15.4     0     0     3     4
#>  5  14.7     8  440    230  3.23  5.34  17.4     0     0     3     4
#>  6  10.4     8  460    215  3     5.42  17.8     0     0     3     4
#>  7  10.4     8  472    205  2.93  5.25  18.0     0     0     3     4
#>  8  16.4     8  276.   180  3.07  4.07  17.4     0     0     3     3
#>  9  17.3     8  276.   180  3.07  3.73  17.6     0     0     3     3
#> 10  15.2     8  276.   180  3.07  3.78  18       0     0     3     3
#> # ... with 22 more rows

既然您想使用字符串,我们可以使用 rlang::parse_expr 正如您已经在自己的回答中发布的那样:

dplyr::arrange( mtcars, !! rlang::parse_expr("desc(hp)"))
#> # A tibble: 32 x 11
#>      mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1  15       8  301    335  3.54  3.57  14.6     0     1     5     8
#>  2  15.8     8  351    264  4.22  3.17  14.5     0     1     5     4
#>  3  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
#>  4  13.3     8  350    245  3.73  3.84  15.4     0     0     3     4
#>  5  14.7     8  440    230  3.23  5.34  17.4     0     0     3     4
#>  6  10.4     8  460    215  3     5.42  17.8     0     0     3     4
#>  7  10.4     8  472    205  2.93  5.25  18.0     0     0     3     4
#>  8  16.4     8  276.   180  3.07  4.07  17.4     0     0     3     3
#>  9  17.3     8  276.   180  3.07  3.73  17.6     0     0     3     3
#> 10  15.2     8  276.   180  3.07  3.78  18       0     0     3     3
#> # ... with 22 more rows

reprex package (v2.0.1)

于 2021-11-03 创建