Pandas:用前一个和下一个非缺失值的平均值动态替换 NaN 值

Posted

技术标签:

【中文标题】Pandas:用前一个和下一个非缺失值的平均值动态替换 NaN 值【英文标题】:Pandas: Dynamically replace NaN values with the average of previous and next non-missing values 【发布时间】:2019-01-04 16:06:46 【问题描述】:

我有一个带有 NaN 值的数据框 df,我想用上一个和下一个非缺失值的平均值动态替换它们。

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

这是处理缺失值的好方法吗?我不能简单地replace them by the average values of each column,因为我的数据是时间序列的,并且会随着时间的推移而增加。 (初始值可能是 0 美元,最终值可能是 100000 美元,所以平均值是 50000 美元,这可能比 NaN 值大/小得多)。

【问题讨论】:

您是否真的依附于您为填写NaN 提供的公式,或者您只是想在前后有一个接近另一个值的值。试试df.interpolate(),它会在NaN 中填充您要查找的值,但不会使用您使用公式计算的确切值 【参考方案1】:

您可以尝试了解几何级数平均值背后的逻辑

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

解释:

第一个 NaN x/2+y/2=1st

2nd NaN 1st/2+y/2=2nd

3rd NaN 2nd/2+y/2+3rd

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

【讨论】:

如果您在同一列中有另一组NaN,这会起作用吗?例如,如果 A 列中的第 7 行和第 8 行也是NaN?我知道这不是问题,只是想知道:) 进展顺利。 +1【参考方案2】:

遇到了一个类似的问题。 以下代码对我有用。

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

也许它也对某人有帮助。

【讨论】:

以上是关于Pandas:用前一个和下一个非缺失值的平均值动态替换 NaN 值的主要内容,如果未能解决你的问题,请参考以下文章

用前一行和下一行的平均值填充 NaN 值 - Python

python pandas使用经验

pandas使用dropna函数删除dataframe中列非缺失值的个数小于某一比例阈值的数据列

pandas 处理缺失值[dropna、drop、fillna]

Pandas:在每组中平均填充缺失值比变换更快

用之前的非缺失值填充缺失的 pandas 数据,按 key 分组