仅向前填充特定值

Forward fill only certain value

我有一个表示对象状态的数组,其中 0 - 对象关闭,1 - 对象打开。

import pandas as pd
import numpy as np

s = [np.nan, 0, np.nan, np.nan, 1, np.nan, np.nan, 0, np.nan, 1, np.nan]
df = pd.DataFrame(s, columns=["s"])
df
      s
0   NaN
1   0.0
2   NaN
3   NaN
4   1.0
5   NaN
6   NaN
7   0.0
8   NaN
9   1.0
10  NaN

我只需要转发其中的 0 值,如下所示。

>>> df_wanted
      s
0   NaN
1   0.0
2   0.0
3   0.0
4   1.0
5   NaN
6   NaN
7   0.0
8   0.0
9   1.0
10  NaN

在这里浏览类似的问题后,我只是比较 ffill-ed 和 bfill-ed 的值并用掩码赋值:

mask = (df.ffill() == 0) & (df.bfill() == 1)
df[mask] = 0
df
      s
0   NaN
1   0.0
2   0.0
3   0.0
4   1.0
5   NaN
6   NaN
7   0.0
8   0.0
9   1.0
10  NaN

但是,如果任何 0 值后面没有跟 1,那将无济于事。考虑到这种情况,还有什么更优雅的解决方案?

一种方法,可能不是很优雅,但对你有用,就是填充所有内容,然后从中选择你的原始系列是 NaN 而你的填充系列是 0。

sf = df.ffill().values[:, 0]
desired = np.where(np.isnan(s) & (sf==0), sf, s)

pandas 也有一个 where 函数,我只是更喜欢 numpy,因为它更通用。

mask = (df.ffill() == 0) 应该足以满足您的用例。

首先,df.ffill 将向前传播最后一个有效观察。因此,0 后的行将由 0s 填充,1 后的行将由 1s 填充。将其与仅 0s0 至 select 行进行比较,并将其用作掩码以获得最终的 df。

示例(添加了一个 0 和几个 NaNs你的 df)

结束
>>> s = [np.nan, 0, np.nan, np.nan, 1, np.nan, np.nan, 0, np.nan, 1, np.nan, np.nan, 0, np.nan, np.nan, np.nan]
>>> df = pd.DataFrame(s, columns=["s"])
>>> df
      s
0   NaN
1   0.0
2   NaN
3   NaN
4   1.0
5   NaN
6   NaN
7   0.0
8   NaN
9   1.0
10  NaN
11  NaN
12  0.0
13  NaN
14  NaN
15  NaN
>>> 
>>> 
>>> df[df.ffill() == 0] = 0
>>> df
      s
0   NaN
1   0.0
2   0.0
3   0.0
4   1.0
5   NaN
6   NaN
7   0.0
8   0.0
9   1.0
10  NaN
11  NaN
12  0.0
13  0.0
14  0.0
15  0.0