如何使用方法链接向前填充列子集?
How to forward fill a column subset with method chaining?
我有一个包含天数信息的数据框。每天有两个阶段。
df = (pd.DataFrame(dict(
day=[0, 1, 2],
phase1=[1, 0, 2],
phase2=[5, 0, 7],
))
目标是提前两个阶段都为 0 的填充日。预期输出如下所示
out_wanted = pd.DataFrame(dict(
day=[0, 1, 2],
phase1=[1, 1, 2],
phase2=[5, 5, 7],
))
我正在寻找此问题的解决方案,它适用于方法链接。语法应该有点像这样:
out_wanted = (
df
.methodA(...)
.methodB(...)
.forward_fill_magic()
.methodC(...)
.methodD(...)
)
我该怎么做?
更新:
让我们假设 df
有两个名为 day
和 x
的列,它们可以包含零,我想避免用 nan 替换其中的任何值。我该怎么做?
df = pd.DataFrame(dict(
day=[0, 1, 2],
phase1=[1, 0, 2],
phase2=[5, 0, 7],
x=[1, 2, 3]
))
当前提出的解决方案给我一个 ValueError
df = (
df.set_index(["day", "x"])
.mask(df.eq(0))
.ffill(downcast= 'infer')
)
-> ValueError: cannot join with no overlapping index names
尝试 set_index
/mask
/ffill
:
df = df.set_index(["day", "x"]).mask(lambda d: d.eq(0)).ffill().reset_index()
ALTERNATIVE_1 :
df = (
df.set_index(["day", "x"])
.replace(0,np.nan)
.ffill(downcast= 'infer')
)
ALTERNATIVE_2 :
df[df.filter(like = 'phase').columns] = df.filter(like= 'phase').mask(df.eq(0)).ffill(downcast='infer')
输出:
phase1 phase2
day
0 1 5
1 1 5
2 2 7
这是一个解决方案,无需设置(后来重置)索引并明确选择要填充的列。它也仅在两列都等于 0 时才填充(我认为这是要求的一部分)。
def forward_fillmagic(df, colnames):
all_zero = df[colnames].eq(0).all(axis=1)
return df.assign(**{
colname: df[colname].mask(all_zero).ffill(downcast="infer")
for colname in colnames
})
df.pipe(forward_fillmagic, ["phase1", "phase2"])
我有一个包含天数信息的数据框。每天有两个阶段。
df = (pd.DataFrame(dict(
day=[0, 1, 2],
phase1=[1, 0, 2],
phase2=[5, 0, 7],
))
目标是提前两个阶段都为 0 的填充日。预期输出如下所示
out_wanted = pd.DataFrame(dict(
day=[0, 1, 2],
phase1=[1, 1, 2],
phase2=[5, 5, 7],
))
我正在寻找此问题的解决方案,它适用于方法链接。语法应该有点像这样:
out_wanted = (
df
.methodA(...)
.methodB(...)
.forward_fill_magic()
.methodC(...)
.methodD(...)
)
我该怎么做?
更新:
让我们假设 df
有两个名为 day
和 x
的列,它们可以包含零,我想避免用 nan 替换其中的任何值。我该怎么做?
df = pd.DataFrame(dict(
day=[0, 1, 2],
phase1=[1, 0, 2],
phase2=[5, 0, 7],
x=[1, 2, 3]
))
当前提出的解决方案给我一个 ValueError
df = (
df.set_index(["day", "x"])
.mask(df.eq(0))
.ffill(downcast= 'infer')
)
-> ValueError: cannot join with no overlapping index names
尝试 set_index
/mask
/ffill
:
df = df.set_index(["day", "x"]).mask(lambda d: d.eq(0)).ffill().reset_index()
ALTERNATIVE_1 :
df = (
df.set_index(["day", "x"])
.replace(0,np.nan)
.ffill(downcast= 'infer')
)
ALTERNATIVE_2 :
df[df.filter(like = 'phase').columns] = df.filter(like= 'phase').mask(df.eq(0)).ffill(downcast='infer')
输出:
phase1 phase2
day
0 1 5
1 1 5
2 2 7
这是一个解决方案,无需设置(后来重置)索引并明确选择要填充的列。它也仅在两列都等于 0 时才填充(我认为这是要求的一部分)。
def forward_fillmagic(df, colnames):
all_zero = df[colnames].eq(0).all(axis=1)
return df.assign(**{
colname: df[colname].mask(all_zero).ffill(downcast="infer")
for colname in colnames
})
df.pipe(forward_fillmagic, ["phase1", "phase2"])