Расчет избыточной суммы наличных в банкомате - PullRequest
0 голосов
/ 04 июля 2019

Я хочу рассчитать избыточную сумму, оставшуюся в банкомате, из заданного набора данных транзакций и пополнений.

Я могу сделать это, зациклив данные, чтобы вычесть транзакции из текущей суммы.Но мне нужно сделать это без использования цикла.

# 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

1 Ответ

0 голосов
/ 04 июля 2019

Прежде всего, мы вычисляем логический столбец, чтобы узнать, был ли он пополнен, как вы делаете.

df['replenished'] = df['R'] > 0

Мы также вычисляем приращение в деньгах, которое будет полезно для выполнения остальныхопераций.

df['increment'] = df['R'] - df['T']

Мы также создаем столбец, который будет иметь желаемые значения в свое время, я назвал его резерв .Для начала, мы делаем накопленную сумму приращений, которая является желаемым значением от первого дня пополнения до следующего.

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

У меня нет опыта в расчете времени исчисления, поэтому я не уверен, что это решение быстрее, чем цикл по всем строкам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...