【发布时间】:2021-10-07 20:40:55
【问题描述】:
我使用tidyeval 编写了一个短函数,该函数将分组变量作为输入,对 mtcars 数据集进行分组并计算每组的出现次数:
test_function <- function(grps){
mtcars %>%
group_by(across({{grps}})) %>%
summarise(Count = n())
}
test_function(grps = c(cyl, gear))
---
cyl gear Count
<dbl> <dbl> <int>
1 4 3 1
2 4 4 8
3 4 5 2
4 6 3 2
5 6 4 4
6 6 5 1
7 8 3 12
8 8 5 2
现在想象一下,对于该示例,我想要每个组 cyl 的小计列。那么有多少汽车有 4(6,8)个气缸?结果应该是这样的:
test_function(grps = c(cyl, gear), subtotalrows = TRUE) ### example function execution
---
cyl gear Count
<dbl> <dbl> <int>
1 4 3 1
2 4 4 8
3 4 5 2
4 4 total 11
5 6 3 2
6 6 4 4
7 6 5 1
8 6 total 7
9 8 3 12
10 8 5 2
11 8 total 14
在这种情况下,我正在寻找的小计列可以简单地使用相同的函数但少一个分组变量来生成:
test_function(grps = cyl)
---
cyl Count
<dbl> <int>
1 4 11
2 6 7
3 8 14
但由于我不想单独使用该函数(甚至不确定这在 R 中是否可行),我想采用不同的方法:据我所知,最好 (and only way)到目前为止,创建小计行是通过独立计算它们和then binding them row wise to the grouped table (i.e.: rbind, bind_rows)。在我的情况下,这意味着只取第一个分组变量,创建小计行,然后将它们绑定到表。但这里是我对 tidyeval 语法有问题的地方。这是我想在函数中执行的伪代码:
test_function <- function(grps, subtotalrows = TRUE){
grouped_result <- mtcars %>%
group_by(across({{grps}})) %>%
summarise(Count = n())
if(subtotalrows == FALSE){
return(grouped_result)
} else {
#pseudocode
group_for_subcalculation <- grps[[1]] #I want the first element of the grps argument
subtotal_result <- mtcars %>%
group_by(across({{group_for_subcalculation}})) %>%
summarise(Count = n()) %>%
mutate(grps[[2]] := "total") %>%
arrange(grps[[1]], grps[[2]], Count)
return(rbind(grouped_result, subtotal_result))
}
}
所以,有两个问题:我很好奇如何提取grps 传递的第一列名称并在以下代码中使用它。其次,这个伪代码示例特定于 grps 传递的 2 列。想象一下,我什至想通过 3 或更多。你会怎么做(循环)?
【问题讨论】:
标签: r dplyr tidyverse user-defined-functions tidyeval