我有一个看起来像的数据集
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可以保持余额。
答案 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