Как заполнить NA значением в других строках в python

У меня есть такая таблица:

 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_id1 и account_id1, на 01/02/2019 сумма должна быть 01/03/2019's100-30=70, а на 01/01/2019 сумма должна быть 01/02/2019's70-(-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

Пожалуйста, предоставьте фактические данные в формате CSV или df = pd.DataFrame({... фрагмент с минимальными данными, чтобы люди могли а) видеть, что вы делаете, и б) копировать пасту, чтобы диагностировать/устранить вашу проблему. Кроме того, вежливо сказать, что вы уже пробовали, и полезно продемонстрировать, как будет выглядеть успешный результат. (result = pd.DataFrame..., например.) Спасибо!

Mike 30.05.2019 06:14

@Mike, спасибо за указание, и я просто редактирую формат. пожалуйста, посмотрите, если вы можете помочь мне с этим! Спасибо

kyle chan 30.05.2019 06:47

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

Umar.H 30.05.2019 07:19

@Datanovice проблема в том, что не у каждой учетной записи есть сумма или транзакция, поэтому есть некоторая учетная запись только с транзакцией. Мне нужно заполнить сумму этого счета. Если моя логика не имеет смысла, не могли бы вы предложить, что я должен сделать, чтобы заполнить эти NA?

kyle chan 31.05.2019 07:15
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
4
129
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Не знаю, поможет ли мое решение, потому что оно грубое. Однако взгляните.

Основная идея состоит в том, чтобы разделить фрейм данных на более мелкие на основе комбинации 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, если моя логика не имеет для вас смысла?

kyle chan 31.05.2019 07:19

Здравствуйте @kylechan, извините за недоразумение. Я думаю, что ваша логика имеет смысл, я просто не понял ее полностью. Минуту назад я отредактировал свой ответ. Теперь, я думаю, это работает так, как вы хотели. Пожалуйста, оставьте комментарий, если я ошибаюсь.

Jaroslav Bezděk 31.05.2019 08:48

Извините за поздний ответ, ваше решение отличное и полезное, я многому научился из вашего ответа. Большое спасибо

kyle chan 04.06.2019 09:17

Я рад, что смог помочь.

Jaroslav Bezděk 04.06.2019 21:34

Другие вопросы по теме