根据组创建新列,并使用基于其他组的总和填充这些列

时间:2018-05-14 16:01:35

标签: r

我有一个像这样设置的data.frame:

Group 1    Group 2   count
   a          aa        1 
   b          ab        6
   c          ac        7

我想重塑一下,报告第1组中每组第2组的计数总和,如下所示:

Group 1    aa  ab  ac
   a        1   0   0 
   b        0   6   0
   c        0   0   7

我已经研究过使用聚合,融合和强制转换,但无法找到将多个组分成单独列的方法。

R: Pivoting using 'spread' function让我得到了一个包含多行第1组的表的地方。

    df %>%
  group_by(`Group 1`) %>%
  mutate(id2 = sequence(n())) %>%
  spread(`Group 2`, "count")

Group 1     id2   aa   ab   ac
   a         1    1    0    0
   a         2    0    4    0
   a         3    0    0    7
   a         4    1    0    0
   a         5    1    0    0
   b         6    0    6    0
   b         7    3    0    0
   b         8    0    0    5

我仍然需要将此减少为每个Group 1条目的总和。

像这样:

Group 1        aa   ab   ac
   a            2    4    7
   b            3    6    5

我以为我可以将链接添加到链中,但我不能让它在多列上工作

2 个答案:

答案 0 :(得分:3)

您可以使用tidyr的spread

library(tidyr)

spread(df, Group_2, count, fill = 0)
#> # A tibble: 3 x 4
#>   Group_1    aa    ab    ac
#>   <chr>   <dbl> <dbl> <dbl>
#> 1 a           1     0     0
#> 2 b           0     6     0
#> 3 c           0     0     7

数据

df <- tibble::tribble(~Group_1, ~Group_2,   ~count,
                      "a",          "aa",        1, 
                      "b",          "ab",        6,
                      "c",          "ac",        7)

对于第二个问题,您可以使用summarise_allsummarise_at折叠生成的data.frame:

df2 %>% 
  group_by(Group_1) %>% 
  summarise_at(c("aa", "ab", "ac"), sum)
#> # A tibble: 2 x 4
#>   Group_1    aa    ab    ac
#>   <fct>   <int> <int> <int>
#> 1 a           3     4     7
#> 2 b           3     6     5

答案 1 :(得分:0)

我在这里找到了一个解决方案:sum multiple columns by group with tapply

使用by函数我能够分离出组。然后我将它返回到带有sapply的data.frame:

df <- df %>%
  group_by(`Group 1`) %>%
  mutate(id2 = sequence(n())) %>%
  spread(`Group 2`, `count`)
df[is.na(df)] <-0 # transform all missing counts to zeros
df <- by(df[,c(3:5)], df$`Group 1`, FUN = colSums)
df <- t(sapply(df, I))
df <- as.data.frame(df)