在 Pandas 系列中填充连续的 NaN

EHB*_*EHB 4 nan series pandas fillna

如果连续 NAN 少于 3 个,我想填充 pandas 系列中的缺失值。

具有缺失值的原始系列:

s=pd.Series(pd.np.random.randn(20))
s[[1,3,5,7,12,13,14,15, 18]]=pd.np.nan
Run Code Online (Sandbox Code Playgroud)

给出:

0     0.444025
1          NaN
2     0.631753
3          NaN
4    -0.577121
5          NaN
6     1.299953
7          NaN
8    -0.252173
9     0.287641
10    0.941953
11   -1.624728
12         NaN
13         NaN
14         NaN
15         NaN
16    0.998952
17    0.195698
18         NaN
19   -0.788995
Run Code Online (Sandbox Code Playgroud)

但是,使用带有限制的 pandas.fillna() 只会填充指定的值数量(而不是预期的 CONSECUTIVE NAN 数量):

s.fillna(value=0, limit=3) #Fails to fill values at position 7 and forward
Run Code Online (Sandbox Code Playgroud)

所需的输出将在位置 1、3、5、7 和 18 处用 0 填充 NAN。它将在位置 12-15 处留下一系列 4 个 NaN。

SO 上的文档和其他帖子尚未解决此问题(例如此处)。文档似乎暗示此限制适用于连续的 NAN,而不是将填充的整个数据集中的整体数量。谢谢!

piR*_*red 5

我们首先nan通过 查找值的位置pd.Series.notna

当我们使用 时cumsum,每当遇到非空值时,我们都会增加累积和,从而为连续nan值生成方便的组。

然而,对于除了第一组(也许是第一组)之外的所有组,我们都以非空值开始。mask因此,我对每组内的空值总数进行求反并求和。

现在我fillna用它来掩盖值总和太多的pd.DataFrame.where地方。nan

mask = s.notna()
c_na = (~mask).groupby(mask.cumsum()).transform('sum')
filled = s.fillna(0).where(c_na.le(3))
s.fillna(filled)

0     1.418895
1     0.000000
2    -0.553732
3     0.000000
4    -0.101532
5     0.000000
6    -1.334803
7     0.000000
8     1.159115
9     0.309093
10   -0.047970
11    0.051567
12         NaN
13         NaN
14         NaN
15         NaN
16    0.623673
17   -0.786857
18    0.000000
19    0.310688
dtype: float64
Run Code Online (Sandbox Code Playgroud)

这是一种使用 Numpy/Pandas 的奇特np.bincount方式pd.factorize

v = s.values
m = np.isnan(v)
f, u = pd.factorize((~m).cumsum())
filled = np.where(
    ~m, v,
    np.where(np.bincount(f, weights=mask)[f] <= 3, 0, np.nan)
)

pd.Series(filled, s.index)

0     1.418895
1     0.000000
2    -0.553732
3     0.000000
4    -0.101532
5     0.000000
6    -1.334803
7     0.000000
8     1.159115
9     0.309093
10   -0.047970
11    0.051567
12         NaN
13         NaN
14         NaN
15         NaN
16    0.623673
17   -0.786857
18    0.000000
19    0.310688
dtype: float64
Run Code Online (Sandbox Code Playgroud)