我花了相当多的时间阅读(以及重读和重读)NSE 和 dplyr 编程的各种解释,但未能解决看起来应该是一个简单问题的问题。 我想提前定义汇总公式,然后编写一个函数将这些公式输入 summarise() 进行评估。
这样做的动机是构建一个特定于一组数据的包,以不需要用户记住的标准方式设置该数据的复杂聚合,但允许他们快速轻松地提取数据和通过只记住聚合的名称来正确聚合它。
这是我的意思的一个例子:
price_per_carat <- ~ sum(price) / sum(carat)
price_depth_ratio <- ~ sum(price) / sum(depth)
summarise_as <- function(.data, ...) {
# some kind of black magic
}
diamonds %>%
group_by(cut, clarity)
summarise_as(price_per_carat, price_depth_ratio)
# A tibble: 40 x 4
# Groups: cut [?]
cut clarity price_per_carat price_depth_ratio
<ord> <ord> <dbl> <dbl>
1 Fair I1 2721.185 56.37119
2 Fair SI2 4297.840 80.31302
3 Fair SI1 4362.573 65.84666
4 Fair VS2 4715.875 65.60159
5 Fair VS1 4734.064 66.17081
6 Fair VVS2 4843.546 53.29967
7 Fair VVS1 5824.159 64.07653
8 Fair IF 4030.679 31.83685
9 Good I1 2989.670 57.94697
10 Good SI2 4424.404 73.58696
# ... with 30 more rows
如果不是很清楚,我基本上是想找到一种方法让summarise_as(price_per_carat, price_depth_ratio)
表现得像我输入的summarise(price_per_carat = sum(price) / sum(carat), price_depth_ratio = sum(price) / sum(depth))
。
我尝试了各种形式的 quo()、enquo()、as.formula、deparse(substitute()) 等,试图让它工作,但都失败了。 这样做的正确方法是什么?
如果您想使用公式,这是一种方法:
library(tidyverse)
library(rlang)
#>
#> Attaching package: 'rlang'
#> The following objects are masked from 'package:purrr':
#>
#> %@%, %||%, as_function, flatten, flatten_chr, flatten_dbl,
#> flatten_int, flatten_lgl, invoke, list_along, modify, prepend,
#> rep_along, splice
summarise_as <- function(.data, ...) {
dots <- quos(...)
names <- map_chr(dots, ~as.character(quo_get_expr(.x)))
names(dots) <- names
get_expr <- function(q){
formula <- eval_tidy(quo_get_expr(q), quo_get_env(q))
expr(!!formula[[2]])
}
exprs <- map( dots, get_expr)
summarise(.data, !!!exprs)
}
price_per_carat <- ~ sum(price) / sum(carat)
price_depth_ratio <- ~ sum(price) / sum(depth)
diamonds %>%
group_by(cut, clarity) %>%
summarise_as(price_per_carat, price_depth_ratio)
#> # A tibble: 40 x 4
#> # Groups: cut [?]
#> cut clarity price_per_carat price_depth_ratio
#> <ord> <ord> <dbl> <dbl>
#> 1 Fair I1 2721. 56.4
#> 2 Fair SI2 4298. 80.3
#> 3 Fair SI1 4363. 65.8
#> 4 Fair VS2 4716. 65.6
#> 5 Fair VS1 4734. 66.2
#> 6 Fair VVS2 4844. 53.3
#> 7 Fair VVS1 5824. 64.1
#> 8 Fair IF 4031. 31.8
#> 9 Good I1 2990. 57.9
#> 10 Good SI2 4424. 73.6
#> # ... with 30 more rows
也许@lionel- 有更好的方法
也许这更容易:
library(tidyverse)
library(rlang)
#>
#> Attaching package: 'rlang'
#> The following objects are masked from 'package:purrr':
#>
#> %@%, %||%, as_function, flatten, flatten_chr, flatten_dbl,
#> flatten_int, flatten_lgl, invoke, list_along, modify, prepend,
#> rep_along, splice
exprs <- list(
price_per_carat = expr(sum(price) / sum(carat)),
price_depth_ratio = expr(sum(price) / sum(depth))
)
diamonds %>%
group_by(cut, clarity) %>%
summarise(!!!exprs)
#> # A tibble: 40 x 4
#> # Groups: cut [?]
#> cut clarity price_per_carat price_depth_ratio
#> <ord> <ord> <dbl> <dbl>
#> 1 Fair I1 2721. 56.4
#> 2 Fair SI2 4298. 80.3
#> 3 Fair SI1 4363. 65.8
#> 4 Fair VS2 4716. 65.6
#> 5 Fair VS1 4734. 66.2
#> 6 Fair VVS2 4844. 53.3
#> 7 Fair VVS1 5824. 64.1
#> 8 Fair IF 4031. 31.8
#> 9 Good I1 2990. 57.9
#> 10 Good SI2 4424. 73.6
#> # ... with 30 more rows
由reprex 包(v0.2.0) 于
我现在就关闭这个。 也许考虑https://community.rstudio.com的问题不仅仅是问题。
这个老问题已自动锁定。 如果您认为您发现了相关问题,请提交一个新问题(使用 reprex)并链接到此问题。 https://reprex.tidyverse.org/
最有用的评论
也许这更容易:
由reprex 包(v0.2.0) 于