仅向前填充特定值
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
填充。将其与仅 0s
的 0
至 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
我有一个表示对象状态的数组,其中 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
填充。将其与仅 0s
的 0
至 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