如何在dplyr中避免使用省略号…?

huangapple go评论116阅读模式
英文:

How to avoid ellipsis ... in dplyr?

问题

  1. 我想创建一个接受分组参数的函数。它可以是单个或多个变量。我希望它看起来像这样:
  2. ```R
  3. wanted <- function(data, groups, other_params){
  4. data %>% group_by( {{groups}} ) %>% count()
  5. }

这只在给定单个组时有效,但在存在多个组时会出错。我知道可以使用省略号 ... 来实现以下功能(但我想要的语法是 groups = something):

  1. not_wanted <- function(data, ..., other_params){
  2. data %>% group_by( ... ) %>% count()
  3. }

以下是完整的代码:

  1. library(dplyr)
  2. library(magrittr)
  3. iris$group2 <- rep(1:5, 30)
  4. wanted <- function(data, groups, other_params){
  5. data %>% group_by( {{groups}} ) %>% count()
  6. }
  7. not_wanted <- function(data, ..., other_params){
  8. data %>% group_by( ... ) %>% count()
  9. }
  10. # 正常运行
  11. wanted(iris, groups = Species )
  12. not_wanted(iris, Species, group2)
  13. # 无法正常运行
  14. wanted(iris, groups = vars(Species, group2) )
  15. wanted(iris, groups = c(Species, group2) )
  16. wanted(iris, groups = vars("Species", "group2") )
  17. # Error: Column `vars(Species, group2)` must be length 150 (the number of rows) or one, not 2
  1. <details>
  2. <summary>英文:</summary>
  3. I want to create a function that takes a grouping argument. Which can be a single or multiple variables. I want it to look like this:

wanted <- function(data, groups, other_params){
data %>% group_by( {{groups}} ) %>% count()
}

  1. This work only when a single group is given but breaks when there are multiple groups. I know it&#39;s possible to use the following with ellipsis `...` (But I want the syntax `groups = something`):

not_wanted <- function(data, ..., other_params){
data %>% group_by( ... ) %>% count()
}

  1. Here is the entire code:

library(dplyr)
library(magrittr)

iris$group2 <- rep(1:5, 30)

wanted <- function(data, groups, other_params){
data %>% group_by( {{groups}} ) %>% count()
}

not_wanted <- function(data, ..., other_params){
data %>% group_by( ... ) %>% count()
}

works

wanted(iris, groups = Species )
not_wanted(iris, Species, group2)

doesn't work

wanted(iris, groups = vars(Species, group2) )
wanted(iris, groups = c(Species, group2) )
wanted(iris, groups = vars("Species", "group2") )

Error: Column vars(Species, group2) must be length 150 (the number of rows) or one, not 2

答案1

得分: 5

你们把事情弄得太复杂了,这样就可以正常工作:

  1. library(tidyverse)
  2. wanted <- function(data, groups){
  3. data %>% count(!!!groups)
  4. }
  5. mtcars %>% wanted(groups = vars(mpg, disp, hp))

一个 tibble: 31 x 4

  1. mpg disp hp n


1 10.4 460 215 1
2 10.4 472 205 1
3 13.3 350 245 1
4 14.3 360 245 1
5 14.7 440 230 1
6 15 301 335 1
7 15.2 276. 180 1
8 15.2 304 150 1
9 15.5 318 150 1
10 15.8 351 264 1

… 其他 21 行

英文:

You guys are over complicating things, this works just fine:

  1. library(tidyverse)
  2. wanted &lt;- function(data, groups){
  3. data %&gt;% count(!!!groups)
  4. }
  5. mtcars %&gt;% wanted(groups = vars(mpg,disp,hp))
  6. # A tibble: 31 x 4
  7. mpg disp hp n
  8. &lt;dbl&gt; &lt;dbl&gt; &lt;dbl&gt; &lt;int&gt;
  9. 1 10.4 460 215 1
  10. 2 10.4 472 205 1
  11. 3 13.3 350 245 1
  12. 4 14.3 360 245 1
  13. 5 14.7 440 230 1
  14. 6 15 301 335 1
  15. 7 15.2 276. 180 1
  16. 8 15.2 304 150 1
  17. 9 15.5 318 150 1
  18. 10 15.8 351 264 1
  19. # … with 21 more rows

答案2

得分: 0

三重感叹号运算符和rlang包中的parse_quos函数将起作用。有关更多信息,请参见 https://stackoverflow.com/a/49941635/6086135

  1. library(dplyr)
  2. library(magrittr)
  3. iris$group2 <- rep(1:5, 30)
  4. vec <- c("Species", "group2")
  5. wanted <- function(data, groups){
  6. data %>% count(!!!rlang::parse_quos(groups, rlang::current_env()))
  7. }
  8. wanted(iris, vec)
  9. #> # A tibble: 15 x 3
  10. #> Species group2 n
  11. #> <fct> <int> <int>
  12. #> 1 setosa 1 10
  13. #> 2 setosa 2 10
  14. #> 3 setosa 3 10
  15. #> 4 setosa 4 10
  16. #> 5 setosa 5 10
  17. #> 6 versicolor 1 10
  18. #> 7 versicolor 2 10
  19. #> 8 versicolor 3 10
  20. #> 9 versicolor 4 10
  21. #> 10 versicolor 5 10
  22. #> 11 virginica 1 10
  23. #> 12 virginica 2 10
  24. #> 13 virginica 3 10
  25. #> 14 virginica 4 10
  26. #> 15 virginica 5 10
  27. # Created on 2020-01-06 by the reprex package (v0.3.0)
英文:

The triple bang operator and parse_quos from the rlang package will do the trick. For more info, see e.g. https://stackoverflow.com/a/49941635/6086135

<!-- language-all: lang-r -->

  1. library(dplyr)
  2. library(magrittr)
  3. iris$group2 &lt;- rep(1:5, 30)
  4. vec &lt;- c(&quot;Species&quot;, &quot;group2&quot;)
  5. wanted &lt;- function(data, groups){
  6. data %&gt;% count(!!!rlang::parse_quos(groups, rlang::current_env()))
  7. }
  8. wanted(iris, vec)
  9. #&gt; # A tibble: 15 x 3
  10. #&gt; Species group2 n
  11. #&gt; &lt;fct&gt; &lt;int&gt; &lt;int&gt;
  12. #&gt; 1 setosa 1 10
  13. #&gt; 2 setosa 2 10
  14. #&gt; 3 setosa 3 10
  15. #&gt; 4 setosa 4 10
  16. #&gt; 5 setosa 5 10
  17. #&gt; 6 versicolor 1 10
  18. #&gt; 7 versicolor 2 10
  19. #&gt; 8 versicolor 3 10
  20. #&gt; 9 versicolor 4 10
  21. #&gt; 10 versicolor 5 10
  22. #&gt; 11 virginica 1 10
  23. #&gt; 12 virginica 2 10
  24. #&gt; 13 virginica 3 10
  25. #&gt; 14 virginica 4 10
  26. #&gt; 15 virginica 5 10

<sup>Created on 2020-01-06 by the reprex package (v0.3.0)</sup>

答案3

得分: 0

以下是翻译好的部分:

这是另一种避免在函数调用中使用引号的选项。我承认它并不是很漂亮。

  1. library(tidyverse)
  2. wanted <- function(data, groups){
  3. grouping <- gsub(x = rlang::quo_get_expr(enquo(groups)), pattern = "\\((.*)?\\)", replacement = "\")[-1]
  4. data %>% group_by_at(grouping) %>% count()
  5. }
  6. iris$group2 <- rep(1:5, 30)
  7. wanted(iris, groups = c(Species, group2) )
  8. #> # A tibble: 15 x 3
  9. #> # Groups: Species, group2 [15]
  10. #> Species group2 n
  11. #> <fct> <int> <int>
  12. #> 1 setosa 1 10
  13. #> 2 setosa 2 10
  14. #> 3 setosa 3 10
  15. #> 4 setosa 4 10
  16. #> 5 setosa 5 10
  17. #> 6 versicolor 1 10
  18. #> 7 versicolor 2 10
  19. #> 8 versicolor 3 10
  20. #> 9 versicolor 4 10
  21. #> 10 versicolor 5 10
  22. #> 11 virginica 1 10
  23. #> 12 virginica 2 10
  24. #> 13 virginica 3 10
  25. #> 14 virginica 4 10
  26. #> 15 virginica 5 10

希望这对您有所帮助。

英文:

Here is another option to avoid quotations in the function call. I admit its not very pretty though.

  1. library(tidyverse)
  2. wanted &lt;- function(data, groups){
  3. grouping &lt;- gsub(x = rlang::quo_get_expr(enquo(groups)), pattern = &quot;\\((.*)?\\)&quot;, replacement = &quot;\&quot;)[-1]
  4. data %&gt;% group_by_at(grouping) %&gt;% count()
  5. }
  6. iris$group2 &lt;- rep(1:5, 30)
  7. wanted(iris, groups = c(Species, group2) )
  8. #&gt; # A tibble: 15 x 3
  9. #&gt; # Groups: Species, group2 [15]
  10. #&gt; Species group2 n
  11. #&gt; &lt;fct&gt; &lt;int&gt; &lt;int&gt;
  12. #&gt; 1 setosa 1 10
  13. #&gt; 2 setosa 2 10
  14. #&gt; 3 setosa 3 10
  15. #&gt; 4 setosa 4 10
  16. #&gt; 5 setosa 5 10
  17. #&gt; 6 versicolor 1 10
  18. #&gt; 7 versicolor 2 10
  19. #&gt; 8 versicolor 3 10
  20. #&gt; 9 versicolor 4 10
  21. #&gt; 10 versicolor 5 10
  22. #&gt; 11 virginica 1 10
  23. #&gt; 12 virginica 2 10
  24. #&gt; 13 virginica 3 10
  25. #&gt; 14 virginica 4 10
  26. #&gt; 15 virginica 5 10

huangapple
  • 本文由 发表于 2020年1月6日 19:52:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/59611638.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定