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]
我只能找到这个答案,这不是同一个问题:
ffill
和 bfill
的解决方案
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
我正在尝试执行以下操作:
假设我在 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]
我只能找到这个答案,这不是同一个问题:
ffill
和 bfill
的解决方案
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