Dplyr: summarise_at 对不同的变量使用不同的函数

创建于 2017-09-13  ·  3评论  ·  资料来源: tidyverse/dplyr

当我在dplyr中使用group_by和summary时,自然可以对不同的变量应用不同的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 做到这一点? 显然,对于这个例子,这是不必要的,但是如果我有很多要取平均值的变量、很多中位数等,这将很有用。

显然,这个问题对于所有新的 _all、_at 和 _if 都是一样的。 也许这是一个仍在开发中的功能; 如果是这样,我会很高兴看到它尽快发布。

最有用的评论

@profdave ,不知道它是否会帮助你,但这里有一些例子来说明我理解你想要的

首先,提醒一下summarize_at旨在将一个或多个函数应用于选定的列。

library(dplyr, warn.conflicts = F)
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_at(vars(x, y), funs(min, max))
#> # A tibble: 3 x 5
#>   category x_min y_min x_max y_max
#>      <chr> <dbl> <dbl> <dbl> <dbl>
#> 1        a     4     3     7     9
#> 2        b     2     0     8     8
#> 3        c     1     1     3     9

我知道您想将几个函数映射到一些不同的特定列。
使用purrr中的tidyverse ,我们可以像这样绕过它来说明:

library(purrr)
list(c("x"), c("y")) %>% 
  map2(lst(min = min, max = max), ~ df %>% group_by(category) %>% summarise_at(.x, .y)) %>% 
  reduce(inner_join)
#> Joining, by = "category"
#> # A tibble: 3 x 3
#>   category     x     y
#>      <chr> <dbl> <dbl>
#> 1        a     4     9
#> 2        b     2     8
#> 3        c     1     9

在上面的例子中,首先你选择一些列来应用列表中的函数,你将它们映射到一个长度相同的列表中,并使用你想要的不同函数,它将分别应用于.x.ysummarize_at 。 最后,您通过加入( reduce在列表上应用函数)将结果合并到一个 data.frame 中

它可以使用summarize at每个功能,例如将多个函数应用于多个列。

list(.vars = lst("x", "y", c("y", "z")),
     .funs = lst(min, max, funs(mean = mean, median = median))) %>% 
  pmap(~ df %>% group_by(category) %>% summarise_at(.x, .y)) %>% 
  reduce(inner_join, by = "category")
#> # A tibble: 3 x 7
#>   category     x     y y_mean    z_mean y_median z_median
#>      <chr> <dbl> <dbl>  <dbl>     <dbl>    <dbl>    <dbl>
#> 1        a     4     9      6 2.6666667        6        0
#> 2        b     2     8      3 5.6666667        1        8
#> 3        c     1     9      6 0.6666667        8        1

您可以对所有summarise_*函数执行相同操作。

这是你想要的结果吗? 如果没有,我将删除此帖子。

最终,我不知道我们是否可以实现一个函数来做到这一点,或者将它包含在summarise_at行为中。 但是,与此同时,上面的示例可以帮助澄清 FR 并帮助您。

所有3条评论

@profdave ,不知道它是否会帮助你,但这里有一些例子来说明我理解你想要的

首先,提醒一下summarize_at旨在将一个或多个函数应用于选定的列。

library(dplyr, warn.conflicts = F)
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_at(vars(x, y), funs(min, max))
#> # A tibble: 3 x 5
#>   category x_min y_min x_max y_max
#>      <chr> <dbl> <dbl> <dbl> <dbl>
#> 1        a     4     3     7     9
#> 2        b     2     0     8     8
#> 3        c     1     1     3     9

我知道您想将几个函数映射到一些不同的特定列。
使用purrr中的tidyverse ,我们可以像这样绕过它来说明:

library(purrr)
list(c("x"), c("y")) %>% 
  map2(lst(min = min, max = max), ~ df %>% group_by(category) %>% summarise_at(.x, .y)) %>% 
  reduce(inner_join)
#> Joining, by = "category"
#> # A tibble: 3 x 3
#>   category     x     y
#>      <chr> <dbl> <dbl>
#> 1        a     4     9
#> 2        b     2     8
#> 3        c     1     9

在上面的例子中,首先你选择一些列来应用列表中的函数,你将它们映射到一个长度相同的列表中,并使用你想要的不同函数,它将分别应用于.x.ysummarize_at 。 最后,您通过加入( reduce在列表上应用函数)将结果合并到一个 data.frame 中

它可以使用summarize at每个功能,例如将多个函数应用于多个列。

list(.vars = lst("x", "y", c("y", "z")),
     .funs = lst(min, max, funs(mean = mean, median = median))) %>% 
  pmap(~ df %>% group_by(category) %>% summarise_at(.x, .y)) %>% 
  reduce(inner_join, by = "category")
#> # A tibble: 3 x 7
#>   category     x     y y_mean    z_mean y_median z_median
#>      <chr> <dbl> <dbl>  <dbl>     <dbl>    <dbl>    <dbl>
#> 1        a     4     9      6 2.6666667        6        0
#> 2        b     2     8      3 5.6666667        1        8
#> 3        c     1     9      6 0.6666667        8        1

您可以对所有summarise_*函数执行相同操作。

这是你想要的结果吗? 如果没有,我将删除此帖子。

最终,我不知道我们是否可以实现一个函数来做到这一点,或者将它包含在summarise_at行为中。 但是,与此同时,上面的示例可以帮助澄清 FR 并帮助您。

非常感谢@cdrv ,看起来这正是我在谈论的。 我会更仔细地研究它(并使自己 100% 了解 purrr 的最新情况)以更好地理解它。 但是将这个功能整合到 dplyr 中真的那么难吗? 当然,您比我更了解,但我认为这对普通用户非常有帮助。

library(dplyr, warn.conflicts = FALSE)

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) %>%
  summarise_all(funs(mean, median, first))
#> # A tibble: 3 x 10
#>   category x_mean y_mean z_mean x_median y_median z_med… x_fi… y_fi… z_fi…
#>   <chr>     <dbl>  <dbl>  <dbl>    <dbl>    <dbl>  <dbl> <dbl> <dbl> <dbl>
#> 1 a          6.00   6.00  2.67      7.00     6.00   0     4.00  6.00  8.00
#> 2 b          5.00   3.00  5.67      5.00     1.00   8.00  2.00  8.00  8.00
#> 3 c          2.00   6.00  0.667     2.00     8.00   1.00  2.00  1.00  1.00
此页面是否有帮助?
0 / 5 - 0 等级