【问题标题】:How to specify sorting variable with desc() for dplyr::arrange using string?如何使用字符串为 dplyr::arrange 指定带有 desc() 的排序变量?
【发布时间】:2021-12-16 05:13:17
【问题描述】:

以下代码应按降序对列 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

【问题讨论】:

  • 你想要result = dplyr::arrange( mtcars, -hp)
  • 也许更方便的解决方案:result <- mtcars[order(-hp),]。我不知道为什么您当前的代码不起作用。
  • 谢谢,但我想将“desc(hp)”作为字符串传递,而不是硬编码。
  • 你必须parse这个表达式。

标签: r dplyr rlang


【解决方案1】:

为了解释这个问题,我们需要看看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 创建于 2021-11-03 (v2.0.1)

【讨论】:

    【解决方案2】:

    这是我的误解。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-17
      相关资源
      最近更新 更多