【发布时间】:2020-06-15 23:32:04
【问题描述】:
我想提供一个面向用户的函数,该函数允许将任意分组变量传递给摘要函数,并可选择指定其他参数进行过滤,但默认情况下为 NULL(因此未计算)。
我理解为什么下面的示例会失败(因为它在 homeworld 所属的位置不明确,而另一个 arg 优先),但我不确定在这种情况下正确传递点的最佳方法是什么。理想情况下,下面对fun 的第二次和第三次调用的结果将返回相同的结果。
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
fun <- function(.df, .species = NULL, ...) {
.group_vars <- rlang::ensyms(...)
if (!is.null(.species)) {
.df <- .df %>%
dplyr::filter(.data[["species"]] %in% .species)
}
.df %>%
dplyr::group_by(!!!.group_vars) %>%
dplyr::summarize(
ht = mean(.data[["height"]], na.rm = TRUE),
.groups = "drop"
)
}
fun(.df = starwars, .species = c("Human", "Droid"), species, homeworld)
#> # A tibble: 19 x 3
#> species homeworld ht
#> <chr> <chr> <dbl>
#> 1 Droid Naboo 96
#> 2 Droid Tatooine 132
#> 3 Droid <NA> 148
#> 4 Human Alderaan 176.
#> 5 Human Bespin 175
#> 6 Human Bestine IV 180
#> 7 Human Chandrila 150
#> 8 Human Concord Dawn 183
#> 9 Human Corellia 175
#> 10 Human Coruscant 168.
#> 11 Human Eriadu 180
#> 12 Human Haruun Kal 188
#> 13 Human Kamino 183
#> 14 Human Naboo 168.
#> 15 Human Serenno 193
#> 16 Human Socorro 177
#> 17 Human Stewjon 182
#> 18 Human Tatooine 179.
#> 19 Human <NA> 193
fun(.df = starwars, .species = NULL, homeworld)
#> # A tibble: 49 x 2
#> homeworld ht
#> <chr> <dbl>
#> 1 Alderaan 176.
#> 2 Aleen Minor 79
#> 3 Bespin 175
#> 4 Bestine IV 180
#> 5 Cato Neimoidia 191
#> 6 Cerea 198
#> 7 Champala 196
#> 8 Chandrila 150
#> 9 Concord Dawn 183
#> 10 Corellia 175
#> # … with 39 more rows
fun(.df = starwars, homeworld)
#> Error in fun(.df = starwars, homeworld): object 'homeworld' not found
<sup>Created on 2020-06-15 by the [reprex package](https://reprex.tidyverse.org) (v0.3.0)</sup>
我知道我可以通过以下方式达到预期的结果:
fun <- function(.df, .species = NULL, .groups = NULL) {
.group_vars <- rlang::syms(purrr::map(.groups, rlang::as_string))
...
}
但我正在寻找使用... 的解决方案,或者允许用户将字符串或符号传递给.groups,例如.groups = c(species, homeworld) 或 .groups = c("species", "homeworld")。
【问题讨论】:
-
传递一个空参数怎么样?
fun(.df = starwars, ,homeworld)否则需要在...中传递.species。 -
@RonakShah NULL 默认值背后的一点是,我希望用户不必担心传递给
.species的内容,并且默认行为是不过滤。执行您的建议相当于只要求用户明确指定fun(.df = starwars, .species = NULL, homeworld)。 -
我仍然没有在您的编辑中看到任何可以消除我的答案有效的内容。