Прерывание условной совокупной суммы pandas python - PullRequest
2 голосов
/ 22 апреля 2020

У меня есть следующий фрейм данных с попытками расходов (или транзакций) от разных пользователей, каждая попытка имеет дату и сумму.

user  date amount
1     1    6    
1     2    5    
1     3    2    
1     4    3    
1     5    1    
2     1    11    
2     2    12    
2     3    5    
2     4    8    
2     5    1    

Допустим, я хочу наложить произвольный лимит на общую сумму потратил и проверил, через какие транзакции go (потому что пользователь не превышает лимит), а какие нет, допустим, лимит равен 10. Желаемый результат будет:

user  date amount approved spent remaining_credit
1     1    6      1        6     4
1     2    5      0        6     4
1     3    2      1        8     2
1     4    3      0        8     2
1     5    1      1        9     1
2     1    11     0        0     10
2     2    12     0        0     10
2     3    5      1        5     5
2     4    8      0        5     5
2     5    1      1        6     4

В любом случае, чтобы рассчитать любой из 3 последних столбцов работ, чтобы решить мою проблему.
Первый (утвержденный, столбец номер 4) будет иметь 1 каждый раз, когда сумма операции меньше предела минус сумма суммы, потраченной предварительно .
Второй (потраченный) имеет совокупные расходы по утвержденным транзакциям.
Третий (remaing_credit) имеет оставшийся кредит после каждой предпринятой попытки.
Я пытался:

d1['spent'] = d1.sort_values('date').groupby('user')['amount'].cumsum()
d1['spent'] = d1.sort_values(['user','date']).spent.mask(d1.spent > limit).fillna(method='pat')

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

1 Ответ

1 голос
/ 22 апреля 2020

Это можно сделать, создав собственную функцию, в которой вы будете перебирать данные для создания каждого столбца, а затем groupby.apply:

def calcul_spendings (ser, val_max=1):
    arr_am = ser.to_numpy()
    arr_sp = np.cumsum(arr_am)
    arr_ap = np.zeros(len(ser))
    for i in range(len(arr_am)):
        if arr_sp[i]>val_max: # check if the 
            arr_sp[i:] -= arr_am[i]
        else:
            arr_ap[i] = 1
    return pd.DataFrame({'approved':arr_ap, 
                         'spent': arr_sp, 
                         'remaining_credit':val_max-arr_sp}, 
                        index=ser.index)

df[['approved','spent','remaining_credit']] = df.sort_values('date').groupby('user')['amount'].apply(calcul_spendings, val_max=10)
print (df)
   user  date  amount  approved  spent  remaining_credit
0     1     1       6       1.0      6                 4
1     1     2       5       0.0      6                 4
2     1     3       2       1.0      8                 2
3     1     4       3       0.0      8                 2
4     1     5       1       1.0      9                 1
5     2     1      11       0.0      0                10
6     2     2      12       0.0      0                10
7     2     3       5       1.0      5                 5
8     2     4       8       0.0      5                 5
9     2     5       1       1.0      6                 4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...