我目前正在重复很多代码,因为我需要summarize
始终将相同的列用于不同的组。如何仅编写一次summarize
函数(始终相同),但要逐个定义输出名称和group_by
参数,如何有效地做到这一点?
一个最小的例子:
col1 <- c("UK", "US", "UK", "US")
col2 <- c("Tech", "Social", "Social", "Tech")
col3 <- c("0-5years", "6-10years", "0-5years", "0-5years")
col4 <- 1:4
col5 <- 5:8
df <- data.frame(col1, col2, col3, col4, col5)
result1 <- df %>%
group_by(col1, col2) %>%
summarize(sum1 = sum(col4, col5))
result2 <- df %>%
group_by(col2, col3) %>%
summarize(sum1 = sum(col4, col5))
result3 <- df %>%
group_by(col1, col3) %>%
summarize(sum1 = sum(col4, col5))
答案 0 :(得分:5)
使用 combn :
combn(colnames(df)[1:3], 2, FUN = function(x){
df %>%
group_by(.dots = x) %>%
summarize(sum1 = sum(col4, col5))
}, simplify = FALSE)
答案 1 :(得分:2)
要在自己的函数中使用dplyr,可以使用整洁的评估。这样做的原因是dplyr评估dplyr代码的方式,这种方式称为非标准评估,它包装了所有不像常规R代码那样的行为。我建议阅读:
https://tidyeval.tidyverse.org/modifying-inputs.html#modifying-quoted-expressions
summarizefunction <- function(data, ..., sumvar1, sumvar2) {
groups <- enquos(...)
sumvar1 <- enquo(sumvar1)
sumvar2 <- enquo(sumvar2)
result <- data %>%
group_by(!!!groups) %>%
summarise(sum1 = sum(!!sumvar1, !!sumvar2))
return(result)
}
summarizefunction(df, col1, col2, sumvar1 = col4, sumvar2 = col5)
您可以使用enquo
关键字来包装引号参数,以防止它们立即被评估。您可以使用!!
(称为bang bang)运算符取消对参数的引用。我认为这是最灵活和可重用的解决方案,即使您不得不编写更多初始代码。
答案 2 :(得分:1)
首先,您需要使用以下函数来评估变量:
library(tidyverse)
res_func <- function(x, y){
df %>%
group_by(!!as.symbol(x), !!as.symbol(y)) %>%
summarize(sum1 = sum(col4, col5))
}
发挥魅力:
res_func("col1", "col2")
# A tibble: 4 x 3
# Groups: col1 [2]
col1 col2 sum1
<fct> <fct> <int>
1 UK Social 10
2 UK Tech 6
3 US Social 8
4 US Tech 12
我们可以使用assign
创建一个函数,以您通过函数传递的参数来命名框架:
res_func2 <- function(x, y){
assign(paste0("result_", x, y),
df %>%
group_by(!!as.symbol(x), !!as.symbol(y)) %>%
summarize(sum1 = sum(col4, col5)),
envir = parent.frame())
}
这仅通过运行result_col1col2
res_func2("col1", "col2")
的新df。
> result_col1col2
# A tibble: 4 x 3
# Groups: col1 [2]
col1 col2 sum1
<fct> <fct> <int>
1 UK Social 10
2 UK Tech 6
3 US Social 8
4 US Tech 12
答案 3 :(得分:1)
在以下情况下,您也可以使用purrr::partial
:
library(purrr)
summarize45 <- partial(summarize, sum1 = sum(col4, col5))
result1b <- df %>%
group_by(col1, col2) %>%
summarize45()
identical(result1, result1b)
# [1] TRUE
或进一步推动它:
gb_df <- partial(group_by, df)
result1c <- gb_df(col1, col2) %>% summarize45()
identical(result1, result1c)
# [1] TRUE