Python – заполнить NULL предыдущим значением записи в столбце

import pandas as pd

df = pd.DataFrame([['NewJersy',0,'2020-08-29'],
                   ['NewJersy',12,'2020-08-30'],
                   ['NewJersy',12,'2020-08-31'],
                   ['NewJersy',None,'2020-09-01'],
                   ['NewJersy',None,'2020-09-02'],
                   ['NewJersy',None,'2020-09-03'],
                   ['NewJersy',5,'2020-09-04'],
                   ['NewJersy',5,'2020-09-05'],
                   ['NewJersy',None,'2020-09-06'],
                   ['NewYork',None,'2020-08-29'],
                   ['NewYork',None,'2020-08-30'],
                   ['NewYork',8,'2020-08-31'],
                   ['NewYork',7,'2020-09-01'],
                   ['NewYork',None,'2020-09-02'],
                   ['NewYork',None,'2020-09-03']],
                   columns=['FName', 'FVal', 'GDate'])

print(df)

Я хочу заполнить значение NULL предыдущими значениями записи. Например, столбец FValue имеет значения NULL для 20-09-01 до 20-09-03. Значение NULL должно быть заменено значением 12, взятым из предыдущего допустимого значения, т. е. из 20-08-31.

Кроме того, если значение даты 2020-08-29 равно нулю, его следует заменить нулем, поскольку это первая дата, и у нее нет предыдущей записи.

Я пробовал код ниже, но не работал

df['F'] = df['F'].fillna(method='ffill')

Проверьте ожидаемые значения здесь: Заполнить пустые значения image

Спасибо


person Suresh Kasu    schedule 06.09.2020    source источник
comment
Можете ли вы создать воспроизводимый пример ваших данных: stackoverflow.com/questions/20109391/   -  person AlexisG    schedule 06.09.2020


Ответы (3)


Вы можете попробовать это:

df.GDate = pd.to_datetime(df.GDate)
for i in range(len(df)):
    if (np.isnan(df.FVal.loc[i])) and (i > 0):
        if (df.GDate.loc[i]-df.GDate.loc[i-1]).days == 1:
            print((df.GDate.loc[i]-df.GDate.loc[i-1]).days)
            df.FVal.loc[i] = df.FVal.loc[i-1]
        else:
            df.FVal.loc[i] = 0


Вывод

    FName       FVal    GDate
0   NewJersy    0.0     2020-08-29
1   NewJersy    12.0    2020-08-30
2   NewJersy    12.0    2020-08-31
3   NewJersy    12.0    2020-09-01
4   NewJersy    12.0    2020-09-02
5   NewJersy    12.0    2020-09-03
6   NewJersy    5.0     2020-09-04
7   NewJersy    5.0     2020-09-05
8   NewJersy    5.0     2020-09-06
9   NewYork     0.0     2020-08-29
10  NewYork     0.0     2020-08-30
11  NewYork     8.0     2020-08-31
12  NewYork     7.0     2020-09-01
13  NewYork     7.0     2020-09-02
14  NewYork     7.0     2020-09-03
person Mateus Mattos    schedule 06.09.2020
comment
Привет, Матеус. Это решение сработало, но получило предупреждающее сообщение C:\..\AppData\Local\Programs\Python\Python37\lib\site-packages\pandas\core\indexing.py:670: SettingWithCopyWarning: значение пытается быть установить на копию фрагмента из DataFrame См. предостережения в документации: pandas.pydata.org/pandas-docs/stable/user_guide/ iloc._setitem_with_indexer(indexer, value) 1 1 1 1 1 1 - person Suresh Kasu; 08.09.2020

Сначала вы должны убедиться, что ваш DataFrame отсортирован по времени на случай:

df = df.sort_values('GDate').reset_index(drop=True)

Затем вы должны заполнить первое значение 0:

if pd.isnull(df.loc[0, 'FVal']):
    df.loc[0, 'FVal'] = df.loc[0, 'FVal']

А затем вперед заполнить, как вы сделали:

df['FVal'] = df['FVal'].fillna(method='ffill')

Обратите внимание, что имя столбца FVal, а не F.

person Chris    schedule 06.09.2020

Не уверен, что это то, что вы хотите. Но это то, что я бы сделал

>>> import math
>>> for s in df.iterrows():
...     if math.isnan(s[1][1]):
...        df.iloc[s[0],1] = df.iloc[s[0] - 1,1]
...
>>> df
       FName  FVal       GDate
0   NewJersy   0.0  2020-08-29
1   NewJersy  12.0  2020-08-30
2   NewJersy  12.0  2020-08-31
3   NewJersy  12.0  2020-09-01
4   NewJersy  12.0  2020-09-02
5   NewJersy  12.0  2020-09-03
6   NewJersy   5.0  2020-09-04
7   NewJersy   5.0  2020-09-05
8   NewJersy   5.0  2020-09-06
9    NewYork   5.0  2020-08-29
10   NewYork   5.0  2020-08-30
11   NewYork   8.0  2020-08-31
12   NewYork   7.0  2020-09-01
13   NewYork   7.0  2020-09-02
14   NewYork   7.0  2020-09-03
>>>
person Peter Moore    schedule 06.09.2020
comment
Строки 9 и 10 должны быть равны 0, поскольку строка 9 является начальной датой и не имеет предыдущего значения. - person Suresh Kasu; 09.09.2020
comment
@SurishKasu правильно. Во всяком случае, вы поняли идею. Также эффективно использовать itertuples(), так как он быстрее, чем iterrows(). Это связано с тем, что он создает обычные кортежи вместо создания серий панд по мере итерации. В документации указано, что после python 3.7 он возвращает именованные кортежи. - person Peter Moore; 09.09.2020