Как заменить NaN на предыдущие значения в pandas DataFrame?

Предположим, что у меня есть DataFrame с некоторыми NaN s:

 >>> import pandas as pd >>> df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]]) >>> df 0 1 2 0 1 2 3 1 4 NaN NaN 2 NaN NaN 9 

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

  0 1 2 0 1 2 3 1 4 2 3 2 4 2 9 

Я могу просто пропустить весь столбец DataFrame по каждому столбцу, поэтапно, и установить значения напрямую, но есть ли простой (оптимально свободный от цикла) способ достижения этого?

Вы можете использовать метод fillna в DataFrame и указать метод как ffill (forward fill):

 >>> df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]]) >>> df.fillna(method='ffill') 0 1 2 0 1 2 3 1 4 2 3 2 4 2 9 

Этот метод…

распространить [s] последнее действительное наблюдение вперед на следующий действительный

Чтобы идти наоборот, существует также метод bfill .

Этот метод не изменяет DataFrame inplace – вам нужно будет переустановить возвращаемый DataFrame в переменную или указать inplace=True :

 df.fillna(method='ffill', inplace=True) 

Вы можете использовать pandas.DataFrame.fillna с pandas.DataFrame.fillna method='ffill' . 'ffill' означает «форвардная заливка» и будет распространять последнее действительное наблюдение вперед. Альтернативой является 'bfill' который работает одинаково, но наоборот.

 import pandas as pd df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]]) df = df.fillna(method='ffill') print(df) # 0 1 2 #0 1 2 3 #1 4 2 3 #2 4 2 9 

Для этого существует функция прямого синонима, pandas.DataFrame.ffill , чтобы упростить pandas.DataFrame.ffill .

Принятый ответ совершенен. У меня была связанная, но немного другая ситуация, когда мне приходилось заполнять форму, но только внутри групп. Если у кого-то есть такая же потребность, знайте, что fillna работает с объектом DataFrameGroupBy.

 >>> example = pd.DataFrame({'number':[0,1,2,nan,4,nan,6,7,8,9],'name':list('aaabbbcccc')}) >>> example name number 0 a 0.0 1 a 1.0 2 a 2.0 3 b NaN 4 b 4.0 5 b NaN 6 c 6.0 7 c 7.0 8 c 8.0 9 c 9.0 >>> example.groupby('name')['number'].fillna(method='ffill') # fill in row 5 but not row 3 0 0.0 1 1.0 2 2.0 3 NaN 4 4.0 5 4.0 6 6.0 7 7.0 8 8.0 9 9.0 Name: number, dtype: float64 

Одна вещь, которую я заметил при попытке этого решения, заключается в том, что если у вас есть N / A в начале или в конце массива, ffill и bfill не совсем работают. Вам нужны оба.

 In [224]: df = pd.DataFrame([None, 1, 2, 3, None, 4, 5, 6, None]) In [225]: df.ffill() Out[225]: 0 0 NaN 1 1.0 ... 7 6.0 8 6.0 In [226]: df.bfill() Out[226]: 0 0 1.0 1 1.0 ... 7 6.0 8 NaN In [227]: df.bfill().ffill() Out[227]: 0 0 1.0 1 1.0 ... 7 6.0 8 6.0 

ffill теперь есть собственный метод pd.DataFrame.ffill

 df.ffill() 0 1 2 0 1.0 2.0 3.0 1 4.0 2.0 3.0 2 4.0 2.0 9.0