Pandas groupby、bin 和 average

Posted

技术标签:

【中文标题】Pandas groupby、bin 和 average【英文标题】:Pandas groupby, bin and average 【发布时间】:2021-11-20 01:40:55 【问题描述】:

我一直在尝试从每个组的值中对分组和 bin 进行分组并获得平均值,但我似乎找不到直接的方法。

数据框:

code1 code2 code3 day amount
abc1   xyz1   123   1   25
abc1   xyz1   123   2   5
abc1   xyz1   123   3   15
 .      .      .    .   .
 .      .      .    .   .
abc1   xyz1   123   20  10
abc2   xyz1   456   1   4
 .      .      .    .   .
 .      .      .    .   .
abc10  xyz5   890   21  5

我想对 3 个不同的代码进行分组,然后分箱并获得该箱的平均值,以获得这样的数据框:

code1 code2 code3  day    amount
abc1   xyz1   123  [1-3]    15
abc1   xyz1   123  [4-6]    13
abc1   xyz1   123  [7-9]    17
 .      .      .    .       .
 .      .      .    .       .
abc10  xyz5   890  [19-21]  18

我尝试过: df(['code1', 'code2', 'code3'])[day].apply(pd.cut, bins=7) 但没有给我想要的结果,而且我仍然需要 bin 的平均值。

编辑说明:并非所有组的大小都相同,并且并非所有组的天数分布均等,例如,某些组以 20 结束,例如,破坏了直接除以数字的能力。也许这只能通过分组来解决,然后遍历每个组以创建垃圾箱。

感谢任何帮助。

【问题讨论】:

所有组都可以使用所有日期吗?还是每个组的日垃圾箱都不一样? 是的,所有组的日期范围不相等,有些组较早/较晚完成的 bin 大小不同,所以最后一个 bin 可能是 [19-20] 并且也不同不同的运行需要 bin 大小。 【参考方案1】:

试试groupbyagg

df.groupby(df.index // 3).agg(k: ('last' if k != 'day' else lambda x: f'[min(x)-max(x)]') for k in df.columns)

或者只指定列名更好:

df.groupby(df.index // 3).agg('code1': 'last', 'code2': 'last', 'code3': 'last', 'day': lambda x: f'[min(x)-max(x)]', 'amount': 'last')

【讨论】:

如果所有组的大小都相同,这肯定有效,但不幸的是,我的数据集并非如此。我会用这些细节更新我的问题。【参考方案2】:

在每个组中生成您的垃圾箱的好方法是groupby.transform

>>> binned_days = df.groupby(['code1', 'code2', 'code3'])['day'].transform(pd.cut, bins=7, precision=0, right=False)
>>> binned_days
0          [1.0, 4.0)
1          [1.0, 4.0)
2          [1.0, 4.0)
5        [17.0, 20.0)
6    [0.9999, 1.0001)
9    [20.997, 21.003)
Name: day, dtype: interval

符号与您的垃圾箱略有不同,[1.0, 4.0) 而不是[1, 3] - 但含义相同。事实上,由于数据类型是区间,因此很容易转换,即使您应该使用 .apply while the .interval accessor does not exist yet:

>>> binned_days = binned_days.apply(lambda iv: pd.Interval(int(iv.left), int(iv.right), closed='both'))
>>> binned_days
0      [1, 4]
1      [1, 4]
2      [1, 4]
5    [17, 20]
6      [0, 1]
9    [20, 21]
Name: day, dtype: interval

现在我们可以使用列和这些天的定义来计算平均值:

>>> df.groupby(['code1', 'code2', 'code3', binned_days])[['amount']].mean().reset_index()
   code1 code2 code3       day  amount
0   abc1  xyz1   123    [1, 4]    15.0
1   abc1  xyz1   123  [17, 20]    10.0
2  abc10  xyz5   890  [20, 21]     5.0
3   abc2  xyz1   456    [0, 1]     4.0

【讨论】:

以上是关于Pandas groupby、bin 和 average的主要内容,如果未能解决你的问题,请参考以下文章

如何加快pandas groupby bins的agg?

python制作分布图

Pandas高级教程之:GroupBy用法

如何在 pandas 中使用过滤条件和 groupby

Pandas 使用 groupby 和模式填充

pandas如何对value列数据进行分组groupby?