某些条件下的累计和

use*_*628 5 r dplyr

这是我的数据框:

       X   Y  Date   Qty  CumSumA  CumSumB
    1  A   B   1/1     1        1        0
    2  A   A   1/1     2        3        2
    3  A   E   1/1     2        5        2
    4  B   A   1/1     1        1        1
    5  B   B   1/1     3        4        4
    6  B   C   1/1     2        6        4
    7  C   D   1/1     2        2        2
    8  C   E   1/1     4        6        2
    9  C   A   1/1     1        7        2
   10  A   C   1/2     2        2        0
   11  A   D   1/2     3        5        0
   12  A   E   1/2     2        7        0
   13  B   A   1/2     5        5        0
   14  B   B   1/2     1        6        1
   15  B   C   1/2     2        8        1
   16  C   D   1/2     2        2        4
   17  C   E   1/2     1        1        4
   18  C   A   1/2     3        4        4
Run Code Online (Sandbox Code Playgroud)

我得到了CumSumA列

library(dplyr)
data <- data %>% 
        group_by(Date,X) %>% 
        mutate(CumSumA= cumsum(Qty)) 
Run Code Online (Sandbox Code Playgroud)

我如何获得CumSumB列,以便它是Qty以上所有行的累积总和,其中Date(a)列中的X值相同,(b)列中的行值相同Y

因此,例如,第16行的X值为C,Date值为1/2。我想获得值C和值1/2 Qty的所有行的累加和。因此,这将是10加15行,因此CumSumB为2 + 2 = 4。YDate

请注意,X和Y列有140多个唯一变量。

Ren*_*rop 3

该解决方案是建立在data.table并加入allow.cartesian=TRUE

require(data.table)
setDT(DT)
Run Code Online (Sandbox Code Playgroud)

创建一个基础data.tableX我们稍后将使用其列。

DT_X <- DT[,.(X,Y, Date, indx = .I)]
setkey(DT_X, Date, X)
Run Code Online (Sandbox Code Playgroud)

在原始文件中删除X和插入索引DT

DT[,`:=`(X=NULL, indy = .I)]
setkey(DT, Date, Y)
Run Code Online (Sandbox Code Playgroud)

X = Y如果(with )连接数据allow.cartesian=TRUEDT_join如果你好奇的话就看一下。请参阅为什么 data.tables 的 X[Y] 连接不允许完全外连接或左连接?为什么这是一个连接

DT_join <- DT_X[DT, allow.cartesian=TRUE]
Run Code Online (Sandbox Code Playgroud)

indy<=indx是一个标识符,仅取“上面所有行”的总和。

DT_join[!is.na(Y), .(CumSumB=sum(Qty * (indy<=indx))), by=.(X,Y,Date)]
Run Code Online (Sandbox Code Playgroud)

编辑(基于 aosmith 答案):by=.(X,Y,Date)也可以使用by=indx

结果:

    X Y Date CumSumB
 1: A B  1/1       0
 2: A A  1/1       2
 3: A E  1/1       2
 4: B A  1/1       1
 5: B B  1/1       4
 6: B C  1/1       4
 7: C D  1/1       2
 8: C E  1/1       2
 9: C A  1/1       2
10: A C  1/2       0
11: A D  1/2       0
12: A E  1/2       0
13: B A  1/2       0
14: B B  1/2       1
15: B C  1/2       1
16: C D  1/2       4
17: C E  1/2       4
18: C A  1/2       4
Run Code Online (Sandbox Code Playgroud)