首页 > 解决方案 > 计算 ATM 中的超额现金金额

问题描述

我想从给定的交易和补货数据集中计算 ATM 中剩余的超额金额。

我可以通过循环数据以从当前金额中减去交易来做到这一点。但我需要在不使用循环的情况下执行此操作。

# 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

标签: pythonpandastime-series

解决方案


首先,我们计算一个布尔列来知道它是否被补充,就像你做的那样。

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

我对微积分时间的效率没有经验,所以我不确定这个解决方案是否比遍历所有行更快。


推荐阅读