累计加/减取决于标志和帐号R

时间:2019-05-23 11:08:47

标签: r cumulative-sum

我有一个看起来像的数据集

TransAmount   C/D   ACCOUNT BALANCE  NEW_BAL
110            C    500000  130.34  -6128.74
200            D    500000  130.34  -6328.74
210            C    500000  130.34
83.07          C    500009  -1079   -6411.81
113.49         C    500026  112.63  -6525.3
39.74          C    500041  179.2   -6565.04
39.74          C    500041  179.2   -6604.78
80             D    500051  -959.93 -6684.78

New_Bal在这里被错误地解决了。

我希望在帐户级别制定NEW_BAL。

因此,如果这是该帐户的第一个实例,并且C / D为C,则New_Bal = BALANCE-TRANSAMOUNT

如果C / D为D,则New_Bal = BALANCE + TRANSAMOUNT

对于该帐户的所有其他实例,我要使用以前的New_Bal而不是BALANCE。对于每个帐户的所有其他实例,如果C / D = C,则New_Bal = New_Bal(来自先前版本)-TRANSAMOUNT

如果C / D为D,则New_Bal = New_Bal(从先前版本开始)+ TRANSAMOUNT

我想要的输出是:

TransAmount   C/D   ACCOUNT BALANCE  NEW_BAL
110            C    500000  130.34  20.34
200            D    500000  130.34  220.34
210            C    500000  130.34  10.34
83.07          C    500009  -1079   -1162.07
113.49         C    500026  112.63  -0.86
39.74          C    500041  179.2   139.46
39.74          C    500041  179.2   99.72
80             D    500051  -959.93 -879.93

请注意,交易数量不是2的上限,最多可以有40笔,所以我希望NEW_BAL可以保持余额。

1 个答案:

答案 0 :(得分:1)

我认为所需输出的第3行中有一个错字。 NEW_BAL应该为220.34-210 = 10.34。

使用C / D翻转TransAmount的符号后,您可以使用base::Reduce进行累加总和:

df$TransAmount <- ifelse(df$`X.C.D.`=="C", -df$TransAmount, df$TransAmount)
do.call(rbind, by(df, df$ACCOUNT, function(x) {
    x$NEW_BAL <- Reduce(`+`, x$TransAmount[-1], x$BALANCE[1]+x$TransAmount[1], accumulate=TRUE)        
    x
}))

或使用data.table

library(data.table)
setDT(DT)[X.C.D.=='C', TransAmount := -TransAmount][, 
    NEW_BAL := Reduce(`+`, TransAmount[-1L], BALANCE[1L]+TransAmount[1L], accumulate=TRUE), by=ACCOUNT]
DT

输出:

         TransAmount X.C.D. ACCOUNT  BALANCE  NEW_BAL
500000.1     -110.00      C  500000   130.34    20.34
500000.2      200.00      D  500000   130.34   220.34
500000.3     -210.00      C  500000   130.34    10.34
500009        -83.07      C  500009 -1079.00 -1162.07
500026       -113.49      C  500026   112.63    -0.86
500041.6      -39.74      C  500041   179.20   139.46
500041.7      -39.74      C  500041   179.20    99.72
500051         80.00      D  500051  -959.93  -879.93

数据:

df <- read.csv(text="TransAmount,'C/D',ACCOUNT,BALANCE
110,C,500000,130.34
200,D,500000,130.34
210,C,500000,130.34
83.07,C,500009,-1079 
113.49,C,500026,112.63
39.74,C,500041,179.2 
39.74,C,500041,179.2 
80,D,500051,-959.93", header=TRUE)
DT <- df