【问题标题】:Expressing pandas subset using pipe使用管道表示熊猫子集
【发布时间】:2016-02-28 19:28:37
【问题描述】:

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

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

【问题讨论】:

  • 我不明白为什么在这里使用pipe 会有用。 df[(df.a &gt;= 2) &amp; (df.b &lt;= 8)].groupby('x').mean() 会做同样的事情,不是吗?
  • 这是真的@jme,这是一个玩具示例,在我更大的代码中,我有更多的步骤。加上. 运算符让一切看起来更整洁。
  • 这是似曾相识或duplicate :-)
  • 基本上,“如何将filter 步骤放入pipe 中?”

标签: python pandas pipe


【解决方案1】:

只要您可以将步骤归类为返回 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 调用。

【讨论】:

  • 感谢 @Ami,您在 lambda 中使用 df_df 也可以工作吗?
  • 还有,我还能有 .groupby 而不是 .pipe(lambda... .groupby) 吗?
【解决方案2】:

我相信这种方法对于你的过滤步骤和后续操作来说是清楚的。不过,使用loc[(mask1) &amp; (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()
 )

【讨论】:

  • 感谢@Alexander,我还能拥有 .groupby 而不是 .pipe(pd.DataFrame.groupby, 'x') 即与上面代码中使用 .groupby 的方式相同
【解决方案3】:

你可以试试,不过我觉得比较复杂:

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

【讨论】:

    猜你喜欢
    • 2022-11-10
    • 2018-12-12
    • 1970-01-01
    • 2016-03-28
    • 2017-05-05
    • 1970-01-01
    • 2018-01-15
    • 1970-01-01
    • 2017-02-27
    相关资源
    最近更新 更多