熊猫与动态列名聚合

时间:2019-09-18 13:48:04

标签: python pandas aggregate pandas-groupby

我有一个脚本,该脚本生成具有数量不定的value列的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的所有列”的平均值?

5 个答案:

答案 0 :(得分:14)

这样更容易
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

答案 1 :(得分:7)

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

答案 2 :(得分: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

答案 3 :(得分:4)

每个OP的评论

enter image description here

我们可以按'group''group_color'进行分组,而不必冒每个'group_color'唯一的'group'的风险

因此:

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

答案 4 :(得分:1)

您可以使用2种字典,它们可以像这样组合:

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

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