用函数替换多个`summaryize`语句

时间:2019-04-29 12:03:37

标签: r function tidyverse summarize

我目前正在重复很多代码,因为我需要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))

4 个答案:

答案 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