Pandas 在中间向前填充 - 相同的值

Pandas foward fill in between - same values

我正在尝试执行以下操作:

假设我在 pandas 上有以下列,其中总会有两个值顺序相等。

l = [np.nan, np.nan, 10, np.nan, np.nan, np.nan, 10, np.nan, 4, np.nan, 4, 5, np.nan, 5, np.nan,  2, np.nan, 2, 1, 1]

如何只在相似值的区间内填充 NaN 值?

预期输出:

[np.nan, np.nan, 10, 10, 10, 10, 10, np.nan, 4, 4, 4, 5, 5, 5, np.nan,  2, 2, 2, 1, 1]

我只能找到这个答案,这不是同一个问题:

ffillbfill

的解决方案
f = df['col'].ffill()
b = df['col'].bfill()

df['col'].mask(f == b, f)

0      NaN
1      NaN
2     10.0
3     10.0
4     10.0
5     10.0
6     10.0
7      NaN
8      4.0
9      4.0
10     4.0
11     5.0
12     5.0
13     5.0
14     NaN
15     2.0
16     2.0
17     2.0
18     1.0
19     1.0
Name: col, dtype: float64

你可以使用

m = df['l'].eq(df['l']).cumsum()
out = df.groupby(m).apply(lambda g: g.fillna({'l': g['l'].max()}) if g.name % 2 else g)

详细解释:

假设您有数据框

l = [np.nan, np.nan, 10, np.nan, np.nan, np.nan, 10, np.nan, 4, np.nan, 4, 5, np.nan, 5, np.nan,  2, np.nan, 2, 1, 1, np.nan]

df = pd.DataFrame({'l': l})
print(df)

       l
0    NaN
1    NaN
2   10.0
3    NaN
4    NaN
5    NaN
6   10.0
7    NaN
8    4.0
9    NaN
10   4.0
11   5.0
12   NaN
13   5.0
14   NaN
15   2.0
16   NaN
17   2.0
18   1.0
19   1.0
20   NaN

可以利用NaN不等于NaN的特性来创建cumsum.

df['m'] = df['l'].eq(df['l']).cumsum()
print(df)

       l   m
0    NaN   0
1    NaN   0
2   10.0   1
3    NaN   1
4    NaN   1
5    NaN   1
6   10.0   2
7    NaN   2
8    4.0   3
9    NaN   3
10   4.0   4
11   5.0   5
12   NaN   5
13   5.0   6
14   NaN   6
15   2.0   7
16   NaN   7
17   2.0   8
18   1.0   9
19   1.0  10
20   NaN  10

我们可以注意到 True 只成对出现。第一行只能是True或者False,所以不管第一行是什么

  • 第一个 True 对开始 True 的累积和只能是 1
  • 第一对 True 到最后 True 的总和只能是 2

这发生在其他 True 对上:开始的 cumsum True 是奇数,结束的 cumsum True 是偶数。

考虑到这一点,我们可以做一个 groupby 然后只用组中的非非值填充奇数和值。

out = df.groupby(m).apply(lambda g: g.fillna({'l': g['l'].max()}) if g.name % 2 else g)
print(out)

       l
0    NaN
1    NaN
2   10.0
3   10.0
4   10.0
5   10.0
6   10.0
7    NaN
8    4.0
9    4.0
10   4.0
11   5.0
12   5.0
13   5.0
14   NaN
15   2.0
16   2.0
17   2.0
18   1.0
19   1.0
20   NaN