# R: Replenishment amount
# T: Transaction Amount
'''
R T
100 50
0 30
0 10
200 110
0 30
60 20
'''
data = {'Date':pd.date_range('2011-05-03','2011-05-8' ).tolist(),'R':[100,0,0,200,0,60],'T':[50,30,10,110,30,20]}
df = pd.DataFrame(data)
# calculated temporary amount and shift it to subtract future
# transactions from it
df['temp'] = ((df['R']-df['T']).shift(1).bfill())
# Boolean indicating whether ATM was replenished or not
# 1: Replenished, 0: Not Replenished
df['replenished'] = (df['R'] >0).astype(int)
# If replenished subtract transaction amount from the replenishment amount
# otherwise subtract it from temp amount
df['replenished']*df['R']+(np.logical_not(df['replenished']).astype(int))*df['temp']-df['T']
Expected Results:
0 50.0
1 20.0
2 10.0
3 90.0
4 60.0
5 40.0
dtype: float64
Actual Results:
0 50.0
1 20.0
2 -40.0
3 90.0
4 60.0
5 40.0
dtype: float64
答案 0 :(得分:0)
首先,我们计算一个布尔列,以了解是否已对它进行了补充。
df['replenished'] = df['R'] > 0
我们还计算了货币增量,这对执行其余操作很有用。
df['increment'] = df['R'] - df['T']
我们还创建了将在适当的时候具有所需值的列,我将其称为 reserve 。首先,我们计算增量的总和,这是从第一个补货日到下一个补货日的期望值。
df['reserve'] = df['increment'].cumsum()
现在,我们将创建数据帧的辅助别名,这将有助于进行操作而不会丢失原始数据。请记住,此变量不是副本,它指向与原始变量相同的数据:df_aux
中的更改将更改原始变量df
。
df_aux = df
然后,我们可以进行处理问题的循环。
while not df_aux.empty:
df_aux = df_aux.loc[df_aux.loc[df_aux['replenished']].index[0]:]
k = df_aux.at[df_aux.index[0], 'reserve']
l = df_aux.at[df_aux.index[0], 'increment']
df_aux['reserve'] = df_aux['reserve'] - k + l
if len(df_aux) > 1:
df_aux = df_aux.loc[df_aux.index[1]:]
else:
break
首先,我们从下一个补货日开始获取所有数据框。从这一天到下一个补货天,如果初始值等于增量,那么累积的总和将为我们提供理想的结果,因此我们修改了累积总和,以使第一个值符合此条件。
然后,如果这是数据帧的最后一行,那么我们的工作就完成了,我们退出了循环。如果不是,那么我们删除刚才计算的补货日,然后继续进行下一天。
所有这些操作之后,结果(df
)是这样的:
Date R T increment replenished reserve
0 2011-05-03 100 50 50 True 50
1 2011-05-04 0 30 -30 False 20
2 2011-05-05 0 10 -10 False 10
3 2011-05-06 200 110 90 True 90
4 2011-05-07 0 30 -30 False 60
5 2011-05-08 60 20 40 True 40
我对微积分时间没有经验,所以我不确定这种解决方案是否比遍历所有行更快。