У меня есть такая таблица:
df = pd.DataFrame({'customer_id':[1,1,1,1,1,1,2,2,2,2,2,2],
'account_id':[1,1,1,2,2,2,1,1,1,2,2,2],
'date':['01/01/2019','01/02/2019','01/03/2019','01/01/2019','01/02/2019','01/03/2019','01/01/2019','01/02/2019','01/03/2019','01/01/2019','01/02/2019','01/03/2019'],
'amount':[np.NAN,np.NAN,100, np.NAN,200,np.NAN, np.NAN,300,np.NAN, 400, np.NAN,np.NAN],
'transaction':[10,-20,30,10,-20,30,10,-20,30,10,-20,30]})
print(df.head(5))
customer_id account_id date amount transaction
0 1 1 01/01/2019 NaN 10
1 1 1 01/02/2019 NaN -20
2 1 1 01/03/2019 100.0 30
3 1 2 01/01/2019 NaN 10
4 1 2 01/02/2019 200.0 -20
Сумма — это общая сумма на конец данного дня, а транзакция — это дневная сумма транзакции. Проблема здесь в том, что не на каждой учетной записи есть баланс или транзакция. Мне нужно найти способ работать со счетами только с транзакцией
Я хочу fillna
в amount_x
, используя эту логику:
Для каждого Financial_account_id, если amount_x
равно NA
затем проверьте, равно ли значение следующей строки NA
или нет.
Например, здесь для customer_id
1
и account_id
1
, на 01/02/2019
сумма должна быть 01/03/2019's
100-30=70
, а на 01/01/2019
сумма должна быть 01/02/2019's
70-(-20)=90
Идеальный результат должен быть:
df = pd.DataFrame({'customer_id':[1,1,1,1,1,1,2,2,2,2,2,2],
'account_id':[1,1,1,2,2,2,1,1,1,2,2,2],
'date':['01/01/2019','01/02/2019','01/03/2019','01/01/2019','01/02/2019','01/03/2019','01/01/2019','01/02/2019','01/03/2019','01/01/2019','01/02/2019','01/03/2019'],
'amount':[90,70,100, 220,200,230, 320,300,330, 400, 380,410],
'transaction':[10,-20,30,10,-20,30,10,-20,30,10,-20,30]})
print(df.head(5))
customer_id account_id date amount transaction
0 1 1 01/01/2019 90 10
1 1 1 01/02/2019 70 -20
2 1 1 01/03/2019 100 30
3 1 2 01/01/2019 220 10
4 1 2 01/02/2019 200 -20
@Mike, спасибо за указание, и я просто редактирую формат. пожалуйста, посмотрите, если вы можете помочь мне с этим! Спасибо
как мы узнаем, какова данная сумма для любого данного дня и для какого счета? логика мне не очень понятна.
@Datanovice проблема в том, что не у каждой учетной записи есть сумма или транзакция, поэтому есть некоторая учетная запись только с транзакцией. Мне нужно заполнить сумму этого счета. Если моя логика не имеет смысла, не могли бы вы предложить, что я должен сделать, чтобы заполнить эти NA?
Не знаю, поможет ли мое решение, потому что оно грубое. Однако взгляните.
Основная идея состоит в том, чтобы разделить фрейм данных на более мелкие на основе комбинации customer_id
и account_id
. После этого вы заполняете значения в меньших кадрах данных (по вашему алгоритму, описанному выше). В конце концов, вы объединяете их как заполненные.
# imports
import pandas as pd
import numpy as np
# make df, as you have written above
df = pd.DataFrame(
{'customer_id':[1,1,1,1,1,1,2,2,2,2,2,2],
'account_id':[1,1,1,2,2,2,1,1,1,2,2,2],
'date':['01/01/2019','01/02/2019','01/03/2019','01/01/2019','01/02/2019','01/03/2019',
'01/01/2019','01/02/2019','01/03/2019','01/01/2019','01/02/2019','01/03/2019'],
'amount':[np.NAN,np.NAN,100, np.NAN,200,np.NAN, np.NAN,300,np.NAN, 400, np.NAN,np.NAN],
'transaction':[10,-20,30,10,-20,30,10,-20,30,10,-20,30]})
# make a new identifier (combination of customer_id and acount_id)
def get_cid_aid_combination(row):
cid = row['customer_id']
aid = row['account_id']
return f'{cid}-{aid}'
df['cid_aid'] = df.apply(lambda row: get_cid_aid_combination(row), axis=1)
# fill it up
list_with_dfs = []
for cid_aid in df.cid_aid.unique():
df_part = df[df['cid_aid']==cid_aid]
cnt = 0
while cnt < len(df_part):
for i, amount, trans in zip(df_part.index, df_part.amount, df_part.transaction):
if pd.isnull(amount) and i+1 in df_part.index:
if pd.notnull(df_part.loc[i+1, 'amount']):
df_part.loc[i, 'amount'] = df_part.loc[i+1, 'amount'] - df_part.loc[i+1, 'transaction']
if pd.isnull(amount) and i-1 in df_part.index:
if pd.notnull(df_part.loc[i-1, 'amount']):
df_part.loc[i, 'amount'] = df_part.loc[i-1, 'amount'] + df_part.loc[i, 'transaction']
cnt += 1
list_with_dfs.append(df_part)
# make a df with filled amount feature
df = pd.concat(list_with_dfs)
Привет, Ярослав. Спасибо за ответ, я попробовал ваш ответ, но кажется, что в результате некоторые значения дат все еще NA. Например, customer_id=1, account_id=2 и date=03.01.2019, что в идеале должно быть 230 (вчерашняя сумма 200 + транзакция этой даты 30). Не могли бы вы подсказать, что нужно улучшить? У меня проблема в том, что не у каждой учетной записи есть сумма или транзакция, поэтому есть некоторая учетная запись только с транзакцией. Мне нужно пополнить эту сумму счета. Не могли бы вы предложить, как я могу заполнить эти NA, если моя логика не имеет для вас смысла?
Здравствуйте @kylechan, извините за недоразумение. Я думаю, что ваша логика имеет смысл, я просто не понял ее полностью. Минуту назад я отредактировал свой ответ. Теперь, я думаю, это работает так, как вы хотели. Пожалуйста, оставьте комментарий, если я ошибаюсь.
Извините за поздний ответ, ваше решение отличное и полезное, я многому научился из вашего ответа. Большое спасибо
Я рад, что смог помочь.
Пожалуйста, предоставьте фактические данные в формате CSV или
df = pd.DataFrame({...
фрагмент с минимальными данными, чтобы люди могли а) видеть, что вы делаете, и б) копировать пасту, чтобы диагностировать/устранить вашу проблему. Кроме того, вежливо сказать, что вы уже пробовали, и полезно продемонстрировать, как будет выглядеть успешный результат. (result = pd.DataFrame...
, например.) Спасибо!