在dplyr链

时间:2016-09-15 09:02:43

标签: r dplyr

我想添加整体摘要行,同时使用dplyr按组计算摘要。我发现了各种问题,询问如何做到这一点,例如: hereherehere,但没有明确的解决方案。一种可能的方法是执行count两次并绑定行:

mtcars %>% 
  count(cyl, gear) %>% 
  bind_rows(
    count(mtcars, gear)
  )
几乎产生我需要的东西(最左边的列有NA而不是' Total'或类似的):

     cyl  gear     n
   <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
9     NA     3    15
10    NA     4    12
11    NA     5     5

我错过了一个更容易/内置的解决方案吗?

8 个答案:

答案 0 :(得分:16)

使用janitor包中的adorn_totals():

library(janitor)
mtcars %>%
  tabyl(cyl, gear) %>%
  adorn_totals("row") 

   cyl  3  4 5
     4  1  8 2
     6  2  4 1
     8 12  0 2
 Total 15 12 5

要从帖子中获取帖子中的“长”表单,请将tidyr::gather()添加到管道中:

mtcars %>%
  tabyl(cyl, gear) %>%
  adorn_totals("row") %>%
  tidyr::gather(gear, n, 2:ncol(.), convert = TRUE)

     cyl gear  n
1      4    3  1
2      6    3  2
3      8    3 12
4  Total    3 15
5      4    4  8
6      6    4  4
7      8    4  0
8  Total    4 12
9      4    5  2
10     6    5  1
11     8    5  2
12 Total    5  5

自我推销提醒,我撰写了这个包 - 在这里添加这个答案b / c这是一个真正有效的解决方案。

答案 1 :(得分:8)

一个选项是使用do

mtcars %>%
   count(cyl, gear) %>%
   ungroup() %>% 
   mutate(cyl=as.character(cyl)) %>% 
   do(bind_rows(., data.frame(cyl="Total", count(mtcars, gear)))) 
   #or replace the last 'do' step with 
   #bind_rows(cbind(cyl='Total', count(mtcars, gear))) #from  @JonnyPolonsky's comments

#      cyl  gear     n
#   <chr> <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
#9  Total     3    15
#10 Total     4    12
#11 Total     5     5

答案 2 :(得分:6)

@ arkrun的回答是一个不容易添加为评论的答案:

虽然稍微复杂一点,但这种格式允许在数据框中进行先前的修改。在生成表之前存在更长的动词链时很有用。 (您想要更改名称,或只选择特定变量)

mtcars %>%
   count(cyl, gear) %>%
   ungroup() %>% 
   mutate(cyl=as.character(cyl))
bind_rows(group_by(.,gear) %>%
              summarise(n=sum(n)) %>%
              mutate(cyl='Total')) %>%
spread(cyl)

## A tibble: 3 x 5
#   gear   `4`   `6`   `8` Total
#* <dbl> <dbl> <dbl> <dbl> <dbl>
#1     3     1     2    12    15
#2     4     8     4     0    12
#3     5     2     1     2     5

这也可以加倍,以便为点差生成总行。

mtcars %>%
  count(cyl, gear) %>%
  ungroup() %>% 
  mutate(cyl=as.character(cyl),
         gear = as.character(gear)) %>%
  bind_rows(group_by(.,gear) %>%
              summarise(n=sum(n)) %>%
              mutate(cyl='Total')) %>%
  bind_rows(group_by(.,cyl) %>%
              summarise(n=sum(n)) %>%
              mutate(gear='Total')) %>%
  spread(cyl,n,fill=0)

# A tibble: 4 x 5
   gear   `4`   `6`   `8` Total
* <chr> <dbl> <dbl> <dbl> <dbl>
1     3     1     2    12    15
2     4     8     4     0    12
3     5     2     1     2     5
4 Total    11     7    14    32

答案 3 :(得分:5)

以下是接受的答案,它使用dplyr 1.0.0和tidyr 1.0.0中引入的新功能。

我们使用新的tidyr::pivot_wider调整计数。然后使用新的dplyr::rowwisedplyr::c_across对总计列的计数求和。

我们还可以使用tidyr::pivot_longer来获得所需的长格式。

library(dplyr, warn.conflicts = FALSE)
library(tidyr)

cyl_gear_sum <- mtcars %>%
  count(cyl, gear) %>%
  pivot_wider(names_from = gear, values_from = n, values_fill = list(n = 0)) %>%
  rowwise(cyl) %>%
  mutate(gear_total = sum(c_across()))

cyl_gear_sum
#> # A tibble: 3 x 5
#> # Rowwise:  cyl
#>     cyl   `3`   `4`   `5` gear_total
#>   <dbl> <int> <int> <int>      <int>
#> 1     4     1     8     2         11
#> 2     6     2     4     1          7
#> 3     8    12     0     2         14

# total as row
cyl_gear_sum %>% 
  pivot_longer(-cyl, names_to = "gear", values_to = "n")
#> # A tibble: 12 x 3
#>      cyl gear           n
#>    <dbl> <chr>      <int>
#>  1     4 3              1
#>  2     4 4              8
#>  3     4 5              2
#>  4     4 gear_total    11
#>  5     6 3              2
#>  6     6 4              4
#>  7     6 5              1
#>  8     6 gear_total     7
#>  9     8 3             12
#> 10     8 4              0
#> 11     8 5              2
#> 12     8 gear_total    14

reprex package(v0.3.0)于2020-04-07创建

答案 4 :(得分:1)

如果您想拥有真正通用的解决方案,可以结合使用purrr :: map_df,base :: c和base :: sum mtcars %>% purrr::map_df(~c(.x, sum(.x, na.rm=TRUE))) %>% tail

P.S。所有列必须为数字!

答案 5 :(得分:0)

这是我的建议。

  1. 通过powerSet函数查找相关分组变量的组合。
  2. 将数据框拆分为一个列表,按分组变量的powerSet分组
  3. 使用适当的汇总功能(例如均值)汇总数据框
  4. bind_rows结果-汇总现在不适用,因为这些列已在步骤3中删除
  5. 使用适当的名称替换分组变量的NA值。

注意。如果分组变量是数字变量,则它们不会在第3步中删除-因此,我将其突变为字符变量。

powerSetList <- function(df, ...) {
  rje::powerSet(x = c(...))[-1] %>% lapply(function(x, tdf = df) group_by(tdf, .dots=x)) %>% c(list(tibble(df)), .)
} 

mtcars %>% 
  mutate_at(vars("cyl", "gear"), as.character) %>%
  powerSetList("cyl", "gear") %>%
  map(~summarise_if(., is.numeric, .funs = mean)) %>%
  bind_rows() %>%
  replace_na(list(gear = "all gears",
                  cyl = "all cyls"))

答案 6 :(得分:0)

也许可行:

library(dplyr)
mtcars %>%
    # convert cyl column as.character
    mutate_at("cyl",as.character) %>%
    # add a copy of the origina data with cyl column = 'TOTAL'
    bind_rows(mutate(mtcars, cyl="total")) %>%
    group_by(cyl) %>% summarise_all(sum)

答案 7 :(得分:0)

library(tidyverse)

#Pre-process mtcars 
mtcars_pre <-
  as_tibble(mtcars) %>% #remove rownames
  select(cyl, gear) %>% 
  count(cyl, gear) %>% #add row totals
  mutate(
    cyl = as.character(cyl) #Convert to character in order to add "Total"
  )

#> # A tibble: 8 x 3
#>   cyl    gear     n
#>   <chr> <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

mtcars_totals <- 
  mtcars_pre %>%
  bind_rows(
    mtcars_pre %>%
      group_by(gear) %>%
      summarise(across(where(is.numeric), ~ sum(.x, na.rm = TRUE))) %>%
      mutate("cyl" = "Total")
  ) %>% 
  arrange(
    gear
  )

#> # A tibble: 11 x 3
#>    cyl    gear     n
#>    <chr> <dbl> <int>
#>  1 4         3     1
#>  2 6         3     2
#>  3 8         3    12
#>  4 Total     3    15
#>  5 4         4     8
#>  6 6         4     4
#>  7 Total     4    12
#>  8 4         5     2
#>  9 6         5     1
#> 10 8         5     2
#> 11 Total     5     5

由 reprex 包 (v2.0.0) 于 2021 年 7 月 13 日创建