Pandas:动态替换NaN值为前后非缺失值的平均值

6
我有一个数据框 df,其中包含NaN值,我希望动态地用前后非缺失值的平均值替换它们。
In [27]: df 
Out[27]: 
          A         B         C
0 -0.166919  0.979728 -0.632955
1 -0.297953 -0.912674 -1.365463
2 -0.120211 -0.540679 -0.680481
3       NaN -2.027325  1.533582
4       NaN       NaN  0.461821
5 -0.788073       NaN       NaN
6 -0.916080 -0.612343       NaN
7 -0.887858  1.033826       NaN
8  1.948430  1.025011 -2.982224
9  0.019698 -0.795876 -0.046431

例如,A[3]NaN,因此它的值应为 (-0.120211-0.788073)/2 = -0.454142。然后,A[4] 应为 (-0.454142-0.788073)/2 = -0.621108。
因此,结果数据框应如下所示:
In [27]: df 
Out[27]: 
          A         B         C
0 -0.166919  0.979728 -0.632955
1 -0.297953 -0.912674 -1.365463
2 -0.120211 -0.540679 -0.680481
3 -0.454142 -2.027325  1.533582
4 -0.621108 -1.319834  0.461821
5 -0.788073 -0.966089 -1.260202
6 -0.916080 -0.612343 -2.121213
7 -0.887858  1.033826 -2.551718
8  1.948430  1.025011 -2.982224
9  0.019698 -0.795876 -0.046431

这是处理缺失值的好方法吗?我不能简单地用每列的平均值替换它们,因为我的数据是时间序列并且随时间增长而增加。(初始值可能为$0,最终值可能为$100000,因此平均值为$50000,可能比NaN值大/小得多)。


4
你是否真的依赖于你提供的填充“NaN”的公式,或者只是希望得到一个接近前后值的数值?尝试使用df.interpolate(),它会用周围的数值填充“NaN”,但不会使用你用公式计算出的精确数值。 - Ben.T
3个回答

2
你可以尝试理解几何级数背后的平均逻辑。
s=df.isnull().cumsum()
t1=df[(s==1).shift(-1).fillna(False)].stack().reset_index(level=0,drop=True)
t2=df.lookup(s.idxmax()+1,s.idxmax().index)
df.fillna(t1/(2**s)+t2*(1-0.5**s)*2/2)
Out[212]: 
          A         B         C
0 -0.166919  0.979728 -0.632955
1 -0.297953 -0.912674 -1.365463
2 -0.120211 -0.540679 -0.680481
3 -0.454142 -2.027325  1.533582
4 -0.621107 -1.319834  0.461821
5 -0.788073 -0.966089 -1.260201
6 -0.916080 -0.612343 -2.121213
7 -0.887858  1.033826 -2.551718
8  1.948430  1.025011 -2.982224
9  0.019698 -0.795876 -0.046431

解释:

1. 首先,NaN x/2+y/2 = 1st

2. 其次,NaN 1st/2+y/2 = 2nd

3. 再次,NaN 2nd/2+y/2+3rd

然后,x/(2**n)+y(1-(1/2)**n)/(1-1/2) 是关键。


如果在同一列中有另一组NaN,比如说第7行和第8行在A列也是NaN,这个方法是否也适用呢?我知道这不是问题中的内容,只是好奇 :) - Ben.T

0

正如Ben.T所提到的那样

如果您在同一列中有另一组NaN

您可以考虑这个简单的解决方案 :)

for column in df:
    for ind,row in df[[column]].iterrows():
        if ~np.isnan(row[column]):
            previous = row[column]
        else:
            indx = ind + 1
            while np.isnan(df.loc[indx,column]):
                indx += 1
            next = df.loc[indx,column]
            previous = df[column][ind] = (previous + next)/2

0

有一个类似的问题。 以下代码适用于我。

def fill_nan_with_mean_from_prev_and_next(df):
        NANrows = pd.isnull(df).any(1).nonzero()[0]
        null_df = df.isnull()
        for row in NANrows :
            for colum in range(0,df.shape[1]):
                if(null_df.iloc[row][colum]):
                    df.iloc[row][colum] = (df.iloc[row-1][colum]+df.iloc[row-1][colum])/2

        return df

也许这对某些人有帮助。


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