【问题标题】:Group sum on 2 variables and subtraction from total对 2 个变量进行分组总和并从总数中减去
【发布时间】:2021-05-04 15:31:02
【问题描述】:

我有一个data.table,格式如下:-

library(data.table)
b <- data.table(Code_Nm = c(rep("a", 3), rep("b", 3), rep("d", 3)),
            Year = rep(2011:2013, 3), total = rep(10, 9),
            a = c(rep(0, 3), 1:6), b = c(7:9, 0, 0, 0, 10:12), d = c(13:18, 0, 0, 0))
b

#   Code_Nm Year total a  b  d
#1:       a 2011    10 0  7 13
#2:       a 2012    10 0  8 14
#3:       a 2013    10 0  9 15
#4:       b 2011    10 1  0 16
#5:       b 2012    10 2  0 17
#6:       b 2013    10 3  0 18
#7:       d 2011    10 4 10  0
#8:       d 2012    10 5 11  0
#9:       d 2013    10 6 12  0

我想获得一个data.table,这样名为actual 的最后一列的值等于total 减去每个Code_Nm 的年度组的总和。 IE。对于a 中的2011,它是10 减去所有2011 值的总和,但来自a 列。这等于10 - (1+4)

对于2012 中的a 类似,它是10 减去所有2012 值的总和,但来自列a。这等于10 - (2+5)

2011 中的b 类似,它是10 减去所有2011 值的总和,但来自列b。这等于10 - (7+10)。对于2012 中的b,它是10 减去所有2012 值的总和,但来自列b。这等于10 - (8+11)

d 列也是如此。

最终结果如下data.table:-

b <- data.table(Code_Nm = c(rep("a", 3), rep("b", 3), rep("d", 3)),
            Year = rep(2011:2013, 3), total = rep(10, 9),
            a = c(rep(0, 3), 1:6), b = c(7:9, 0, 0, 0, 10:12), d = c(13:18, 0, 0, 0),
            actual = c(5, 3, 1, -7, -9, -11, -19, -21, -23))
b

#   Code_Nm Year total a  b  d actual
#1:       a 2011    10 0  7 13      5
#2:       a 2012    10 0  8 14      3
#3:       a 2013    10 0  9 15      1
#4:       b 2011    10 1  0 16     -7
#5:       b 2012    10 2  0 17     -9
#6:       b 2013    10 3  0 18    -11
#7:       d 2011    10 4 10  0    -19
#8:       d 2012    10 5 11  0    -21
#9:       d 2013    10 6 12  0    -23

请使用data.table 提供解决方案。

提前致谢。

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    在用感兴趣的列指定.SDcols 并从“总计”中减去之后,我们可以在data.table (.SD) 的子集上使用rowSums

    b[, actual := total  - rowSums(.SD), .SDcols = a:d]
    

    -输出

    b
    #    Code_Nm Year total a b d actual
    #1:       a 2011    10 0 2 3      5
    #2:       a 2012    10 0 3 4      3
    #3:       a 2013    10 0 4 5      1
    #4:       b 2011    10 1 0 6      3
    #5:       b 2012    10 2 0 7      1
    #6:       b 2013    10 3 0 8     -1
    #7:       d 2011    10 4 5 0      1
    #8:       d 2012    10 5 6 0     -1
    #9:       d 2013    10 6 7 0     -3
    

    【讨论】:

    • 嗯,答案是对的。但在解决方案中,实际发生的是第一行的10-(2+3),依此类推。这给出了第一行的正确答案,因为2+3 基本上等于1+4。让我换个问题中的例子,然后,也许你会明白。
    • 我已经编辑了问题,你现在可以试试吗?
    【解决方案2】:

    你可以试试下面的代码

    b[, actual := total - colSums(cbind(a, b, d)[, .SD[, Code_Nm]]), Year][]
    

    给了

       Code_Nm Year total a  b  d actual
    1:       a 2011    10 0  7 13      5
    2:       a 2012    10 0  8 14      3
    3:       a 2013    10 0  9 15      1
    4:       b 2011    10 1  0 16     -7
    5:       b 2012    10 2  0 17     -9
    6:       b 2013    10 3  0 18    -11
    7:       d 2011    10 4 10  0    -19
    8:       d 2012    10 5 11  0    -21
    9:       d 2013    10 6 12  0    -23
    

    【讨论】:

      【解决方案3】:

      更新:

      我的想法是我可以为列a,b,d 转置每个组,然后我仍然可以使用以前的方法total - rowSum(.SD)

      cols1 <- names(b)[4:6]
      cols2 <- paste(names(b)[4:6],2,sep = "")
      
      b[,(cols2):= lapply(split.default(as.data.frame(t(.SD)),cols1),unlist),
        by = Year,
        .SDcols = cols1]
      
      b[, actual := total - rowSums(.SD), .SDcols = cols2]
      b[,(cols2):=NULL][]
      

      上一页

      这是你想要的结果吗?

      b[,actual := total - ( a + b + d)][]
      

      b[, actual := total - apply(.SD,1,sum),.SDcols = c(4:6)][]
      

      【讨论】:

      • 答案是对的,但你能参考我在第一个答案上写的第一条评论吗?然后尝试。
      【解决方案4】:

      这是另一个使用 melt 的选项,然后使用连接通过引用进行更新:

      m <- melt(b, id.vars="Year", measure.vars=c("a","b","d"))[, sum(value), .(Year, Code_Nm=variable)]
      b[, actual := m[.SD, on=.(Code_Nm, Year), i.total - x.V1]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-27
        • 1970-01-01
        • 2021-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-29
        • 1970-01-01
        相关资源
        最近更新 更多