summarise_at为不同的变量使用不同的函数

时间:2017-09-13 03:06:56

标签: r dplyr tidyverse

当我在dplyr中使用group_by和summary时,我可以自然地将不同的汇总函数应用于不同的变量。例如:

    library(tidyverse)

    df <- tribble(
      ~category,   ~x,  ~y,  ~z,
      #----------------------
          'a',      4,   6,   8,
          'a',      7,   3,   0,
          'a',      7,   9,   0,
          'b',      2,   8,   8,
          'b',      5,   1,   8,
          'b',      8,   0,   1,
          'c',      2,   1,   1,
          'c',      3,   8,   0,
          'c',      1,   9,   1
     )

    df %>% group_by(category) %>% summarize(
      x=mean(x),
      y=median(y),
      z=first(z)
    )

导致输出:

    # A tibble: 3 x 4
      category     x     y     z
         <chr> <dbl> <dbl> <dbl>
    1        a     6     6     8
    2        b     5     1     8
    3        c     2     8     1

我的问题是,如何使用summarise_at执行此操作?显然,对于这个例子来说这是不必要的,但假设我有许多变量,我想采取平均值,很多中位数等等。

移至summarise_at后,是否会丢失此功能?我是否必须对所有变量组使用所有函数,然后扔掉那些我不想要的函数?

也许我只是遗漏了一些东西,但我无法弄明白,而且我在文档中也没有看到任何这样的例子。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:6)

这是一个想法。

library(tidyverse)

df_mean <- df %>%
  group_by(category) %>%
  summarize_at(vars(x), funs(mean(.)))

df_median <- df %>%
  group_by(category) %>%
  summarize_at(vars(y), funs(median(.)))

df_first <- df %>%
  group_by(category) %>%
  summarize_at(vars(z), funs(first(.)))

df_summary <- reduce(list(df_mean, df_median, df_first), 
                     left_join, by = "category")

就像你说的那样,这个例子没有必要使用summarise_at。但是,如果您需要通过不同的功能汇总很多列,则此策略可能会起作用。您需要为每个vars(...)指定summarize_at中的列。该规则与dplyr::select函数相同。

更新

这是另一个想法。定义一个修改summarise_at函数的函数,然后使用map2将此函数应用于一个查找列表,该列表显示要应用的变量和相关函数。在此示例中,我将mean应用于xy列,将median应用于z

# Define a function
summarise_at_fun <- function(variable, func, data){
  data2 <- data %>%
    summarise_at(vars(variable), funs(get(func)(.)))
  return(data2)
}

# Group the data
df2 <- df %>% group_by(category)

# Create a look-up list with function names and variable to apply
look_list <- list(mean = c("x", "y"),
                  median = "z")

# Apply the summarise_at_fun
map2(look_list, names(look_list), summarise_at_fun, data = df2) %>%
  reduce(left_join, by = "category")

# A tibble: 3 x 4
  category     x     y     z
     <chr> <dbl> <dbl> <dbl>
1        a     6     6     0
2        b     5     3     8
3        c     2     6     1

答案 1 :(得分:1)

由于您的问题是关于“ summarise_at”的;

这是我的主意:

    timeouts {  
    delete = "60m"
  }