我有一个数据框,我想在其中基于布尔系列向前/向后填充,
df['condition']
。
单个组由一系列
True
值组成,包括将一个条纹与下一个条纹分开的中断 False
条目。
当查看我的数据框时,我的意思非常清楚。我的输入如下所示:
condition_values = [True, True, True, False, True, True, False, True,
True, False, True, True, True]
value_values = [0.1, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan,
np.nan, np.nan, 0.5, np.nan, 0.9, np.nan]
data = {'condition': condition_values,
'value': value_values}
df = pd.DataFrame(data)
condition value
0 True 0.1
1 True NaN
2 True NaN
3 False NaN
4 True NaN
5 True NaN
6 False NaN
7 True NaN
8 True NaN
9 False 0.5
10 True NaN
11 True 0.9
12 True NaN
我想要的输出如下所示:
condition_values = [True, True, True, False, True, True, False, True, True,
False, True, True, True]
value_values = [0.1,0.1, 0.1, 0.1, np.nan, np.nan, np.nan, 0.5, 0.5, 0.5,
0.9, 0.9, 0.9]
data = {'condition': condition_values,
'value': value_values}
df2 = pd.DataFrame(data)
condition value
0 True 0.1
1 True 0.1
2 True 0.1
3 False 0.1
4 True NaN
5 True NaN
6 False NaN
7 True 0.5
8 True 0.5
9 False 0.5
10 True 0.9
11 True 0.9
12 True 0.9
我尝试制作一堆数据帧,按 False、ffill 和 bfill 分割,然后重新连接。必须有一种更快的方法。我非常愿意接受提示而不是完整的解决方案 - 我正在尝试以某种方式解决这个问题。
你们确实很接近!您可以尝试如下:
选项 1:
ffill().bfill()
df['value'] = (
df.groupby(
df['condition'].shift().eq(0).cumsum()
.where(df['condition']).ffill()
)['value']
.apply(lambda x: x.ffill().bfill())
.droplevel(0)
)
选项2:
transform(first)
如果每个组只有 one 值(如您的示例中所示),则可以更简单地完成:
df['value'] = (
df.groupby(
df['condition'].shift().eq(0).cumsum()
.where(df['condition']).ffill()
)['value'].transform('first')
)
输出
condition value
0 True 0.1
1 True 0.1
2 True 0.1
3 False 0.1
4 True NaN
5 True NaN
6 False NaN
7 True 0.5
8 True 0.5
9 False 0.5
10 True 0.9
11 True 0.9
12 True 0.9
解释
Series.shift
开始 df['condition']
并检查 Series.eq
为 0(就像您所做的那样)。
Series.where
将False
行“重置”到NaN
并应用Series.ffill
,从而将它们添加到上一组。
df.groupby
,选择“value”列。
groupby.apply
将 Series.ffill
和 Series.bfill
应用于每个组。在这种情况下,您需要在分配给 df.droplevel
之前删除带有
df['value']
的前置索引级别。
groupby.transform
并获得groupby.first
。使用默认设置,这将返回第一个非NaN
值。
我一直在努力。 我相信答案实际上在于 groupby。
s = df.condition.shift(1).eq(0).cumsum()
df['value2'] = df.groupby(s).value.ffill().bfill()
这还不完美,但已经实现了。
好的,问题是 ffill().bfill() 会破坏组,因为第二个填充正在处理系列。明白了:
df['value2'] = df.groupby(s).value.ffill()
df['value2'] = df.groupby(s).value.bfill()