【问题标题】:Pandas aggregate with dynamic column namesPandas 使用动态列名聚合
【发布时间】:2020-01-19 12:01:27
【问题描述】:

我有一个脚本可以生成一个带有不同数量值列的 pandas 数据框。例如,这个 df 可能是

import pandas as pd
df = pd.DataFrame({
'group': ['A', 'A', 'A', 'B', 'B'],
'group_color' : ['green', 'green', 'green', 'blue', 'blue'],
'val1': [5, 2, 3, 4, 5], 
'val2' : [4, 2, 8, 5, 7]
})

  group group_color  val1  val2
0     A       green     5     4
1     A       green     2     2
2     A       green     3     8
3     B        blue     4     5
4     B        blue     5     7

我的目标是获取每个值列的分组平均值。在这种特定情况下(有 2 个值列),我可以使用

df.groupby('group').agg({"group_color": "first", "val1": "mean", "val2": "mean"})

      group_color      val1      val2
group                                
A           green  3.333333  4.666667
B            blue  4.500000  6.000000

但当相关数据框具有更多值列(val3、val4 等)时,这不起作用。 有没有办法动态取“所有其他列”或“名称中包含 val 的所有列”的平均值?

【问题讨论】:

  • 一组的 group_color 是否总是相同的?
  • @QuangHoang:是的,是这样,但我还是想保留它

标签: python pandas aggregate pandas-groupby


【解决方案1】:

比较简单

df.groupby('group').agg(lambda x : x.head(1) if x.dtype=='object' else x.mean())
Out[63]: 
      group_color      val1      val2
group                                
A           green  3.333333  4.666667
B            blue  4.500000  6.000000

【讨论】:

  • 不错的解决方案!你能解释一下为什么非数字列的 dtype 是 object 吗?
  • @MartijnVanAttekum 这是熊猫、字符串和其他都归类为对象的数据类型
【解决方案2】:

如果您的group_color 在一组中始终相同,您可以这样做:

df.pivot_table(index=['group','group_color'],aggfunc='mean')

输出:

                       val1      val2
group group_color                    
A     green        3.333333  4.666667
B     blue         4.500000  6.000000

在另一种情况下,您可以构建字典并将其传递给agg

agg_dict = {f: 'first' if f=='group_color' else 'mean' for f in df.columns[1:]}
df.groupby('group').agg(agg_dict)

哪个输出:

      group_color      val1      val2
group                                
A           green  3.333333  4.666667
B            blue  4.500000  6.000000

【讨论】:

  • 你是pivot_table 答案是正确的。我使用了几乎相同的东西,但添加了reset_index
【解决方案3】:

不幸的是,您将不得不分别应用这两个聚合函数(或者重复 "valn": "mean"valx 列一样多次)。 Groupby.agg 可以使用字典,但键必须是单独的列。

我这样做的方法是使用DataFrame.filter 选择数据帧的子集,其中列遵循valx 的格式,用平均值聚合,然后用聚合结果分配新列列:

(df.filter(regex=r'^val').groupby(df.group).mean()
   .assign(color = df.group_color.groupby(df.group).first()))

         val1      val2    color
group                           
A      3.333333  4.666667  green
B      4.500000  6.000000   blue

【讨论】:

    【解决方案4】:

    根据 OP 的评论

    我们可以同时按'group''group_color' 进行分组,而不会有每个'group' 有多个唯一'group_color' 的风险

    因此:

    df.groupby(['group', 'group_color']).mean().reset_index(level=1)
    
          group_color      val1      val2
    group                                
    A           green  3.333333  4.666667
    B            blue  4.500000  6.000000
    

    【讨论】:

      【解决方案5】:

      您可以使用 2 个可以像这样组合的词典:

      df.groupby('group').agg({**{'group_color': 'first'}, **{c: 'mean' for c in df.columns if c.startswith('val')}})
      

      在这种情况下,您有一个 dict 具有固定聚合,另一个具有动态列选择。

      【讨论】:

        猜你喜欢
        • 2018-11-13
        • 2019-07-06
        • 2016-03-30
        • 1970-01-01
        • 2014-06-25
        • 2014-04-28
        • 2018-10-17
        • 1970-01-01
        • 2019-03-04
        相关资源
        最近更新 更多