如何用pandas DataFrame中的先前值替换NaN?

zeg*_*jan 103 python nan dataframe python-3.x pandas

假设我有一个带有NaNs 的DataFrame :

>>> 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
Run Code Online (Sandbox Code Playgroud)

我需要做的是用它上面的同一列中NaN的第一个非NaN值替换每个值.假设第一行永远不会包含a NaN.因此,对于前面的示例,结果将是

   0  1  2
0  1  2  3
1  4  2  3
2  4  2  9
Run Code Online (Sandbox Code Playgroud)

我可以逐个循环遍历整个DataFrame,逐个元素并直接设置值,但是有一种简单(最佳无循环)的方法来实现这一目标吗?

Ale*_*ley 157

您可以fillna在DataFrame上使用该方法并将方法指定为ffill(向前填充):

>>> 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
Run Code Online (Sandbox Code Playgroud)

这个方法......

将最后有效观察值传播到下一个有效值

换句话说,还有一种bfill方法.

此方法不会修改DataFrame - 您需要将返回的DataFrame重新绑定到变量,或者指定inplace=True:

df.fillna(method='ffill', inplace=True)
Run Code Online (Sandbox Code Playgroud)


Ern*_*ler 21

接受的答案是完美的.我有一个相关但略有不同的情况,我必须填写前进,但只在组内.如果有人有相同的需求,请知道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
Run Code Online (Sandbox Code Playgroud)

  • 正是我正在寻找的东西,ty (2认同)

Ffi*_*ydd 14

您可以使用pandas.DataFrame.fillnamethod='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
Run Code Online (Sandbox Code Playgroud)

为此,还有一个直接的同义词功能pandas.DataFrame.ffill,使事情更简单.


Md *_*lam 10

您可以使用fillna删除或替换 NaN 值。

NaN删除

import pandas as pd

df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])

df.fillna(method='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
Run Code Online (Sandbox Code Playgroud)

NaN替换

df.fillna(0) # 0 means What Value you want to replace 
     0    1    2
0  1.0  2.0  3.0
1  4.0  0.0  0.0
2  0.0  0.0  9.0
Run Code Online (Sandbox Code Playgroud)

参考pandas.DataFrame.fillna


小智 9

我在尝试这个解决方案时注意到的一件事是,如果你在数组的开头或结尾有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
Run Code Online (Sandbox Code Playgroud)


piR*_*red 7

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
Run Code Online (Sandbox Code Playgroud)


Dev*_*cie 5

只有一列版本

  • 最后一个有效值填充 NAN
df[column_name].fillna(method='ffill', inplace=True)
Run Code Online (Sandbox Code Playgroud)
  • 下一个有效值填充 NAN
df[column_name].fillna(method='backfill', inplace=True)
Run Code Online (Sandbox Code Playgroud)


Suv*_*uvo 5

只是同意ffill方法,但一个额外的信息是您可以使用关键字参数限制前向填充limit

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

>>> df
     0    1   2
0  1.0  2.0   3
1  NaN  NaN   6
2  NaN  NaN   9

>>> df[1].fillna(method='ffill', inplace=True)
>>> df
     0    1    2
0  1.0  2.0    3
1  NaN  2.0    6
2  NaN  2.0    9
Run Code Online (Sandbox Code Playgroud)

现在使用limit关键字参数

>>> df[0].fillna(method='ffill', limit=1, inplace=True)

>>> df
     0    1  2
0  1.0  2.0  3
1  1.0  2.0  6
2  NaN  2.0  9
Run Code Online (Sandbox Code Playgroud)