Pandas按照前后非NaN值的平均值填充NaN值。

26

我希望填充 df 中的空值(nan),使用相邻元素的平均值。

考虑一个数据框:

df = pd.DataFrame({'val': [1,np.nan, 4, 5, np.nan, 10, 1,2,5, np.nan, np.nan, 9]})
    val
0   1.0
1   NaN
2   4.0
3   5.0
4   NaN
5   10.0
6   1.0
7   2.0
8   5.0
9   NaN
10  NaN
11  9.0

我期望的输出是:

    val
0   1.0
1   2.5
2   4.0
3   5.0
4   7.5
5   10.0
6   1.0
7   2.0
8   5.0
9   7.0 <<< deadend
10  7.0 <<< deadend
11  9.0

我已经查看了其他解决方案,例如填充包含NaN的单元格,使用前后值的平均值,但是如果有两个或两个以上连续的np.nan,这种方法就行不通。

非常感谢您提供的任何帮助!


你是否真的希望两个或更多连续的NaN被填充相同的值?难道你不是真的想要在定义的值之间进行线性插值吗? - pipe
1
@pipe 我确实考虑过这个方法,但似乎比使用“平均值”填充更加复杂和计算量大,而且我的实际数据集可能超过数千万行,所以这并不是必要的。 - Chris
df.val.interpolate(limit=1).fillna(method="ffill") - shantanuo
2个回答

49

使用 ffill + bfill,然后除以2:


df = (df.ffill()+df.bfill())/2

print(df)
     val
0    1.0
1    2.5
2    4.0
3    5.0
4    7.5
5   10.0
6    1.0
7    2.0
8    5.0
9    7.0
10   7.0
11   9.0

编辑:如果第一个和最后一个元素都包含NaN,则使用(Dark的建议):

df = pd.DataFrame({'val':[np.nan,1,np.nan, 4, 5, np.nan, 
                          10, 1,2,5, np.nan, np.nan, 9,np.nan,]})
df = (df.ffill()+df.bfill())/2
df = df.bfill().ffill()

print(df)
     val
0    1.0
1    1.0
2    2.5
3    4.0
4    5.0
5    7.5
6   10.0
7    1.0
8    2.0
9    5.0
10   7.0
11   7.0
12   9.0
13   9.0

10
如果第一个和最后一个元素都是NaN,则在使用上述解决方案之后使用df.bfill().ffill() - Bharath M Shetty

6

虽然在连续出现多个 nan 的情况下,该方法不能产生您指定的精确输出,但访问此页面的其他用户实际上可能更喜欢使用 interpolate() 方法的效果:

df = df.interpolate()

print(df)
     val
0    1.0
1    2.5
2    4.0
3    5.0
4    7.5
5   10.0
6    1.0
7    2.0
8    5.0
9    6.3
10   7.7
11   9.0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接