首页 > 解决方案 > 在 dplyr 1.0 中使用 tidyeval 一次汇总多个函数

问题描述

假设我们有一个数据框,

library(tidyverse)
library(rlang)

df <- tibble(id = rep(c(1:2), 10),
             grade = sample(c("A", "B", "C"), 20, replace = TRUE))

我们想得到按 id 分组的成绩的平均值,

df %>% 
    group_by(id) %>% 
    summarise(
        n = n(),
        mu_A = mean(grade == "A"),
        mu_B = mean(grade == "B"),
        mu_C = mean(grade == "C")
    )

我正在处理一个有多个条件的情况(在这种情况下是多个等级),并且希望使我的代码更加健壮。我们如何在 dplyr 1.0 中使用 tidyevaluation 来简化这一点?

我说的是通过一次通过所有等级来生成多个列名的想法,而不会破坏 dplyr 中的管道流,例如

# how to get the mean of A, B, C all at once?
mu_{grade} := mean(grade == {grade})

标签: rdplyrtidyverserlangtidyeval

解决方案


实际上,我从 2 年前写的一篇文章中找到了我自己问题的答案......

我将在下面发布代码,希望能帮助遇到同样问题的任何人。

make_expr <- function(x) {
    x %>%
        map( ~ parse_expr(str_glue("mean(grade == '{.x}')")))
}

# generate multiple expressions
grades <- c("A", "B", "C")
exprs  <- grades %>% make_expr() %>% set_names(paste0("mu_", grades))

# we can 'top up' something extra by adding named element 
exprs <- c(n = parse_expr("n()"), exprs) 

# using the big bang operator `!!!` to force expressions in data frame
df %>% group_by(id) %>% summarise(!!!exprs)

推荐阅读