【问题标题】:subtotals per category over multiple columns多列中每个类别的小计
【发布时间】:2019-01-10 22:13:42
【问题描述】:

我正在寻找一种有效的解决方案,为“id”列中的每个类别的新行中的每一列添加小计。我可以通过使用下面的代码来实现所需的输出,但这种方法对于大型数据集效率不高。是否可以使用数据表来实现这一点?

谢谢!

data <- data.frame(id = c("a","b","a","b","c","c","c","a","a","b"),
               total = c(1,2,3,4,2,3,4,2,3,4),
               total2 = c(2,3,4,2,3,4,5,6,4,2),
               total3 = c(2,3,4,5,6,3,2,3,4,5))

data_new <- data.frame(id = character(), total = numeric(), total2 = 
numeric(), total3 = numeric())

for (i in unique(data$id)){

subset <- data[data$id == i,]

subtotals <- data.frame(id = i, total = sum(subset$total), total2 = 
sum(subset$total2), total3 = sum(subset$total3))

subset <- rbind(subset,subtotals)

data_new <- rbind(data_new, subset)


}

data_new 

【问题讨论】:

    标签: r datatable subtotal


    【解决方案1】:

    这里有一个data.table 解决方案:

    library(data.table)
    setDT(data)
    rbind(data, data[, lapply(.SD,sum), by=id])[order(id)]
    #    id total total2 total3
    # 1:  a     1      2      2
    # 2:  a     3      4      4
    # 3:  a     2      6      3
    # 4:  a     3      4      4
    # 5:  a     9     16     13
    # 6:  b     2      3      3
    # 7:  b     4      2      5
    # 8:  b     4      2      5
    # 9:  b    10      7     13
    #10:  c     2      3      6
    #11:  c     3      4      3
    #12:  c     4      5      2
    #13:  c     9     12     11
    

    by=id 变量分组,然后通过lapply(.SD,sum) 计算除id 之外的每个变量的总和。然后rbind这个回到主集,然后orderid的行。

    【讨论】:

      【解决方案2】:

      这是使用aggregate 的基本 R 解决方案。感谢@thelatemail 简化了原始版本。

      SubTotals = aggregate(data[,2:4], data["id"], sum)
      data_new = rbind(data, SubTotals)
      data_new = data_new[order(data_new$id),]
      data_new
         id total total2 total3
      1   a     1      2      2
      3   a     3      4      4
      8   a     2      6      3
      9   a     3      4      4
      11  a     9     16     13
      2   b     2      3      3
      4   b     4      2      5
      10  b     4      2      5
      12  b    10      7     13
      5   c     2      3      6
      6   c     3      4      3
      7   c     4      5      2
      13  c     9     12     11
      

      【讨论】:

      • list(data$id) 也可以是 data["id"],这样可以避免重命名。甚至aggregate(. ~ id, data, sum)
      • @thelatemail 这是一个很大的改进。我会将它添加到解决方案中。
      【解决方案3】:

      这是一种 tidyverse 风格的方法:

      library(tidyverse)
      
      data_new <- bind_rows(data, 
                            data %>% 
                              group_by(id) %>% 
                              summarise_all(sum)
                            ) %>% 
        arrange(id) %>% 
        print()
      #>    id total total2 total3
      #> 1   a     1      2      2
      #> 2   a     3      4      4
      #> 3   a     2      6      3
      #> 4   a     3      4      4
      #> 5   a     9     16     13
      #> 6   b     2      3      3
      #> 7   b     4      2      5
      #> 8   b     4      2      5
      #> 9   b    10      7     13
      #> 10  c     2      3      6
      #> 11  c     3      4      3
      #> 12  c     4      5      2
      #> 13  c     9     12     11
      

      reprex package (v0.2.1) 于 2019 年 1 月 10 日创建

      【讨论】:

        猜你喜欢
        • 2017-03-24
        • 2022-01-25
        • 1970-01-01
        • 2016-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-21
        • 2011-03-07
        相关资源
        最近更新 更多