我有一个像我这样的子集的数据框:
a b x y
0 1 2 3 -1
1 2 4 6 -2
2 3 6 6 -3
3 4 8 3 -4
df = df[(df.a >= 2) & (df.b <= 8)]
df = df.groupby(df.x).mean()
如何使用pandas管道运算符表达它?
df = (df
.pipe((x.a > 2) & (x.b < 6)
.groupby(df.x)
.apply(lambda x: x.mean())
答案 0 :(得分:3)
只要您可以将某个步骤归类为返回DataFrame的内容,并采用DataFrame(可能包含更多参数),那么您可以使用pipe
。这样做是否有利,是另一个问题。
例如,您可以使用
df\
.pipe(lambda df_, x, y: df_[(df_.a >= x) & (df_.b <= y)], 2, 8)\
.pipe(lambda df_: df_.groupby(df_.x))\
.mean()
注意第一阶段是一个带有3个参数的lambda,其中2和8作为参数传递。这不是唯一的方法 - 它相当于
.pipe(lambda df_: df_[(df_.a >= 2) & (df_.b <= 8)])\
另请注意,您可以使用
df\
.pipe(lambda df_, x, y: df[(df.a >= x) & (df.b <= y)], 2, 8)\
.groupby('x')\
.mean()
此处lambda采用df_
,但在df
上运行,第二个pipe
已替换为groupby
。
第一个改变在这里起作用,但是很重要。 发生工作,因为这是第一个管道阶段。如果它是一个后期阶段,它可能需要一个具有一个维度的DataFrame,并尝试在具有另一个维度的掩码上过滤它,例如。
第二个改变很好。从表面上看,我认为它更具可读性。基本上,任何需要DataFrame并返回一个的东西都可以直接调用或通过pipe
调用。
答案 1 :(得分:2)
我相信这种方法对于您的过滤步骤和后续操作是明确的。但是,使用loc[(mask1) & (mask2)]
可能会更高效。
>>> (df
.pipe(lambda x: x.loc[x.a >= 2])
.pipe(lambda x: x.loc[x.b <= 8])
.pipe(pd.DataFrame.groupby, 'x')
.mean()
)
a b y
x
3 4.0 8 -4.0
6 2.5 5 -2.5
可替换地:
(df
.pipe(lambda x: x.loc[x.a >= 2])
.pipe(lambda x: x.loc[x.b <= 8])
.groupby('x')
.mean()
)
答案 2 :(得分:1)
你可以尝试,但我认为它更复杂:
print df[(df.a >= 2) & (df.b <= 8)].groupby(df.x).mean()
a b x y
x
3 4.0 8 3 -4.0
6 2.5 5 6 -2.5
def masker(df, mask):
return df[mask]
mask1 = (df.a >= 2)
mask2 = (df.b <= 8)
print df.pipe(masker, mask1).pipe(masker, mask2).groupby(df.x).mean()
a b x y
x
3 4.0 8 3 -4.0
6 2.5 5 6 -2.5