累计sum/subtraction 取决于flag和帐号R

Cumulative sum/subtraction dependent on flag and account number R

我有一个数据集看起来

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 是滚动余额。

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

TransAmount符号翻转后C/D可以用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