Pandas动态列名聚合

25

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

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

我的目标是获得每个值列的分组平均值。在这种具体情况下(有两个值列),我可以使用

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 始终是相同的吗? - Quang Hoang
@QuangHoang:是的,情况确实如此,但我仍然希望保留它。 - MartijnVanAttekum
5个回答

16

更加易懂简单

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是对象吗? - MartijnVanAttekum
@MartijnVanAttekum 这是Pandas中的数据类型,字符串和其他的类型都归类为对象。 - BENY

9
如果您的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

1
你的 pivot_table 答案是可行的。我使用了几乎相同的方法,但添加了一个 reset_index - piRSquared

6

很不幸,你必须分别应用这两个汇总函数(或者重复使用"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的评论

enter image description here

我们可以按照'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

2
您可以使用2个字典,并将它们组合在一起,如下所示:
df.groupby('group').agg({**{'group_color': 'first'}, **{c: 'mean' for c in df.columns if c.startswith('val')}})

在这种情况下,您有一个带有固定汇总的dict和另一个带有动态列选择。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接