【问题标题】:Replacing group_by_at(NULL) using across使用 cross 替换 group_by_at(NULL)
【发布时间】:2020-09-28 08:36:27
【问题描述】:

之前,我使用group_by_at 按字符串向量或NULL 进行分组:

library(tidyverse)

grouping_1 <- c("cyl", "vs")
grouping_2 <- NULL

mtcars %>% group_by_at(grouping_1) 
mtcars %>% group_by_at(grouping_2) 

group_by_at 的帮助表示该功能已被取代,应使用across 代替。但是,按 NULL 分组会报错

mtcars %>% group_by(across(grouping_1)) # this works
mtcars %>% group_by(across(grouping_2)) # this gives an error

对我来说,以上述方式使用的group_by_at 很有用,因为在我的函数中,我可以使用相同的代码,而无需每次都检查分组参数是否为空 (NULL)。

【问题讨论】:

  • 来自across 文档:across() 可以轻松地将相同的转换应用于多个列,允许您在summarise()mutate() 中使用select() 语义。因此,我不确定您是否可以在 group_by 语句中使用 across..
  • 如果来自 group_by_all 的文档:“作用域动词 (_if, _at, _all) 已被现有动词中的 cross() 使用所取代。有关详细信息,请参阅 vignette("colwise") 。”
  • 所有在 group_by_all 帮助下的例子都是用cross来替换被取代的函数的例子。
  • 你是对的,我没有检查函数group_by_all。谢谢你让我注意到它

标签: r dplyr tidyverse rlang


【解决方案1】:

使用syms将字符串拼接成group_by使用!!!还是可以的。

library(tidyverse)

grouping_1 <- c("cyl", "vs")
grouping_2 <- NULL

sym_gr_1 <- syms(grouping_1)
sym_gr_2 <- syms(grouping_2)

mtcars %>% group_by(!!! sym_gr_1) # this works

#> # A tibble: 32 x 11
#> # Groups:   cyl, vs [5]
#>      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


mtcars %>% group_by(!!! sym_gr_2) # this works

#> # 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

reprex package (v0.3.0) 于 2020 年 6 月 20 日创建


使用dplyr::across() 另一个选项(在官方方法之上使用all_of 发布在下面的答案中)是将包含变量名称的字符串包装在c() 中。当对象为 NULL 时,这甚至可以工作。但是,结果是一个注释,提醒使用更好地使用all_of

grouping_1 <- c("cyl", "vs")
grouping_2 <- NULL

mtcars %>% group_by(across(c(grouping_1))) 

#> Note: Using an external vector in selections is ambiguous.
#> ℹ Use `all_of(grouping_1)` instead of `grouping_1` to silence this message.
#> ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
#> This message is displayed once per session.

#> # A tibble: 32 x 11
#> # Groups:   cyl, vs [5]
#>      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
mtcars %>% group_by(across(c(grouping_2))) 

#> Note: Using an external vector in selections is ambiguous.
#> ℹ Use `all_of(grouping_2)` instead of `grouping_2` to silence this message.
#> ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
#> This message is displayed once per session.

#> # 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

reprex package (v0.3.0) 于 2021 年 5 月 30 日创建

【讨论】:

    【解决方案2】:

    使用all_of

    library(tidyverse)
    
    mtcars %>% group_by(across(all_of(grouping_1))) # this works
    mtcars %>% group_by(across(all_of(grouping_2))) # this works
    

    【讨论】:

    猜你喜欢
    • 2023-03-11
    • 2016-08-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-02
    • 1970-01-01
    • 2017-11-14
    • 2015-03-20
    • 2019-12-10
    相关资源
    最近更新 更多