Python 上连续 NaN 的缺失值插补

Imputation of Missing Value on Python for Consecutive NaN

编辑:我现在正在寻找一种干净的方法来将我的数据集的缺失值归因于 Python

     a       b         c
0    1       2         Falcon

1    np.nan   3        Falcon

2    np.nan   np.nan   Falcon
  
3    np.nan    4       Bird

4    np.nan   5        Bird
 
5    5        np.nan   Bird

6    6        7        Bird

我需要根据他们的个人群体使用以下条件进行估算。
(1) 对于在其前面的 前一行中具有值的缺失值,通过插值来填充它
(2) 对于在其前面的 前一行中有值的缺失值,用前面或上一行的值填充它
(3) 对于不满足(1)和(2)的缺失值,用0

填充


结果示例为

     a   b      c
0    1   2      Falcon

1    1   3      Falcon

2    0   3      Falcon
  
3    0   4      Bird

4    5   5      Bird

5    5   6      Bird

6    6   7      Bird

我已经尝试了下面评论中提供的代码,但是我未能通过其各自的组进行设置。我该如何在 Python 中进行操作?

这还不是完整的答案,但有一些提示。假设我们在这里处理单个数组(例如,a)。

首先将a首尾的[nan]拼接得到a1。这将简化归集规则的应用。

其次,您现在可以使用三个数组 a1[:-2]、a1[1:-1]、a1[2:] 来获得所有三个移动 window 值。

当然,您需要编写一个函数来根据这三个值估算值,但这很简单:

def impute(xprev, x, xnext):
   if not isnan(x):
      return x
   # the rest of the logic here left as an exercise

提示 2:可能有更有效的构造(如 np.stack),但获得所有三个值的一种简单方法是正常的 zip:

result_list = [impute(prev, this, next) for (prev, this, next) in zip(a1[:-2], a1[1:-1], a1[2:])]
# turn list to array or you can use np.fromiter(( impute(...) for ... ), np.float64) to make array directly from iterable

我希望这些提示足以构建解决方案。

在上面的解决方案中,我应用了几个通用模式,这是我在练习编程时发现的:

  1. 使用方便的停止值填充而不是检查边界索引
  2. 使用zip进行小型搬家windows

注意。也可以为扩展数组 (a1) 生成索引,而不是使用 zip 或 stack。所以我相信会有更多优化的其他答案,因为 Numpy 有很多功能可以提供。此外,上面的 impute 可能会变成 ufunc 并应用于堆叠移位数组 - 但是,如果不进行分析,很难判断它是否比上面的简单列表理解或相应的解决方案更有效指数.

我无法想象一种直接的方式,所以我会为您的每个要求使用一次传递。好的是,由于每次传递都会填充一些值,因此后续传递不会尝试填充它们:

  1. 对于在其前一行和上一行中都有值的缺失值,通过插值法填充

     df[df.isna()&(~df.shift().isna())&(~df.shift(-1).isna())] = df.interpolate()
    
  2. 对于在其前一行或前一行中有值的缺失值,用前一行或前一行值填充它

     df[df.isna()&(~df.shift().isna())] = df.ffill()
     df[df.isna()&(~df.shift(-1).isna())] = df.bfill()
    
  3. 对于不满足(1)和(2)的缺失值,补0

     df.fillna(0)
    

根据您的样本数据,它给出了预期的结果:

     a    b
0  1.0  2.0
1  1.0  3.0
2  0.0  3.5
3  0.0  4.0
4  5.0  5.0
5  5.0  6.0
6  6.0  7.0

确实需要4次操作,但是都是向量化的,所以全局处理时间应该可以接受。