使用管道表达pandas子集

时间:2016-02-28 19:28:37

标签: python pandas pipe

我有一个像我这样的子集的数据框:

   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())

3 个答案:

答案 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