【问题标题】:How to avoid ellipsis ... in dplyr?如何避免省略号......在dplyr?
【发布时间】:2020-04-23 23:16:02
【问题描述】:

我想创建一个带有分组参数的函数。可以是单个或多个变量。我希望它看起来像这样:

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

这仅在给定单个组时有效,但在有多个组时会中断。我知道可以将以下内容与省略号 ... 一起使用(但我想要语法 groups = something):

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

完整代码如下:

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

【问题讨论】:

  • 您能否澄清一下应该为group 工作的变量,length &gt;= 1 的字符向量?另外,为什么不在count() 呼叫中进行分组
  • 只需将您的 {{...}} 更改为 !!! - 然后使用 vars(Species, group2) 的呼叫将起作用 - 请参阅 dplyr.tidyverse.org/articles/…

标签: r dplyr grouping ellipsis


【解决方案1】:

你们把事情复杂化了,这很好用:

library(tidyverse)

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

mtcars %>% wanted(groups = vars(mpg,disp,hp))

# A tibble: 31 x 4
     mpg  disp    hp     n
   <dbl> <dbl> <dbl> <int>
 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
# … with 21 more rows

【讨论】:

  • 正是我想要的。谢谢!
【解决方案2】:

rlang 包中的三重 bang 运算符和 parse_quos 可以解决问题。有关更多信息,请参见例如https://stackoverflow.com/a/49941635/6086135

library(dplyr)

library(magrittr)

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


vec <- c("Species", "group2")


wanted <- function(data, groups){
  data %>%  count(!!!rlang::parse_quos(groups, rlang::current_env()))
}

wanted(iris, vec)
#> # A tibble: 15 x 3
#>    Species    group2     n
#>    <fct>       <int> <int>
#>  1 setosa          1    10
#>  2 setosa          2    10
#>  3 setosa          3    10
#>  4 setosa          4    10
#>  5 setosa          5    10
#>  6 versicolor      1    10
#>  7 versicolor      2    10
#>  8 versicolor      3    10
#>  9 versicolor      4    10
#> 10 versicolor      5    10
#> 11 virginica       1    10
#> 12 virginica       2    10
#> 13 virginica       3    10
#> 14 virginica       4    10
#> 15 virginica       5    10

reprex package (v0.3.0) 于 2020-01-06 创建

【讨论】:

  • 感谢您的回答。砰砰砰!!!解决了这个问题,但我一直在寻找布鲁诺的方法,因为它留下了用vars(group1, group2) 编写常规 dplyr 变量的可能性
【解决方案3】:

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

library(tidyverse)

wanted <- function(data, groups){
  grouping <- gsub(x = rlang::quo_get_expr(enquo(groups)), pattern = "\\((.*)?\\)", replacement = "\\1")[-1]
  data %>% group_by_at(grouping) %>% count()
}


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

wanted(iris, groups = c(Species, group2) )
#> # A tibble: 15 x 3
#> # Groups:   Species, group2 [15]
#>    Species    group2     n
#>    <fct>       <int> <int>
#>  1 setosa          1    10
#>  2 setosa          2    10
#>  3 setosa          3    10
#>  4 setosa          4    10
#>  5 setosa          5    10
#>  6 versicolor      1    10
#>  7 versicolor      2    10
#>  8 versicolor      3    10
#>  9 versicolor      4    10
#> 10 versicolor      5    10
#> 11 virginica       1    10
#> 12 virginica       2    10
#> 13 virginica       3    10
#> 14 virginica       4    10
#> 15 virginica       5    10

【讨论】:

  • 感谢您的回答。砰砰砰!!!解决问题。
猜你喜欢
  • 1970-01-01
  • 2020-11-18
  • 1970-01-01
  • 2019-01-28
  • 1970-01-01
  • 1970-01-01
  • 2021-05-18
  • 1970-01-01
  • 2017-08-30
相关资源
最近更新 更多