【问题标题】:pandas groupby() with custom aggregate function and put result in a new column具有自定义聚合函数的 pandas groupby() 并将结果放入新列
【发布时间】:2019-04-12 04:24:08
【问题描述】:

假设我有一个包含 3 列的数据框。我想按其中一列对其进行分组,并使用自定义聚合函数为每个组计算一个新值。

这个新值具有完全不同的含义,并且它的列不存在于原始数据框中。因此,实际上,我想在groupby() + agg() 转换期间更改数据框的形状。原始数据框看起来像 (foo, bar, baz) 并且有一个范围索引,而生成的数据框只需要有 (qux) 列和 baz 作为索引。

import pandas as pd

df = pd.DataFrame({'foo': [1, 2, 3], 'bar': ['a', 'b', 'c'], 'baz': [0, 0, 1]})
df.head()

#        foo    bar    baz
#   0      1      a      0
#   1      2      b      0
#   2      3      c      1    

def calc_qux(gdf, **kw):
    qux = ','.join(map(str, gdf['foo'])) + ''.join(gdf['bar'])
    return (None, None)  # but I want (None, None, qux)

df = df.groupby('baz').agg(calc_qux, axis=1)  # ['qux'] but then it fails, since 'qux' is not presented in the frame.
df.head()

#      qux
# baz       
#   0  1,2ab
#   1  3c

如果我尝试从聚合函数返回与原始数据帧中的列数不同的值,则上面的代码会产生错误 ValueError: Shape of passed values is (2, 3), indices imply (2, 2)

【问题讨论】:

  • 你想要的输出到底是什么?
  • 没有预期的输出,我不确定我是否理解。但是您可能想要 apply 而不是聚合,并且可能想要返回 pd.Series 而不是 tuple
  • @rahlf23 刚刚添加了一个示例,请查看更新后的问题。
  • @RafaelC apply + series 单值可能有效,但我仍然需要一个组。我可以在应用某些东西时进行分组吗?

标签: python pandas dataframe pandas-groupby


【解决方案1】:

您想在这里使用apply(),因为您不是在单个列上操作(在这种情况下agg() 是合适的):

import pandas as pd

df = pd.DataFrame({'foo': [1, 2, 3], 'bar': ['a', 'b', 'c'], 'baz': [0, 0, 1]})

def calc_qux(x):

    return ','.join(x['foo'].astype(str).values) + ''.join(x['bar'].values)

df.groupby('baz').apply(calc_qux).to_frame('qux')

产量:

       qux
baz       
0    1,2ab
1       3c

【讨论】:

  • 这个解决方案看起来很棒。但是,apply() 的这种用法对我来说似乎违反直觉。每个组最多可能有 N 个值,目标是将它们减少到一个 聚合 值,即 reduce。虽然我对apply() 的理解是它类似于地图
  • apply() 只是将规定的函数(在本例中为 calc_qux)应用于传递的每个“子数据帧”(在本例中为来自 df.groupby('baz') 的每个组)。 apply() 在直接应用于数据帧时,也可以根据 axis 参数按列和按行运行
猜你喜欢
  • 2019-06-08
  • 2017-08-04
  • 2019-12-22
  • 2020-10-05
  • 2015-01-04
  • 1970-01-01
  • 2021-11-05
  • 2019-10-12
  • 2019-11-05
相关资源
最近更新 更多