Pandas groupby 在保留多个聚合的组内排序

Posted

技术标签:

【中文标题】Pandas groupby 在保留多个聚合的组内排序【英文标题】:Pandas groupby sort within groups retaining multiple aggregates 【发布时间】:2018-07-01 18:40:21 【问题描述】:

我想在groupby 返回的组中应用排序和限制,如this question。但是,我有多个聚合,我希望所有聚合都保留在结果中。

这是一个简单的例子:

products = ["A", "B", "C", "D"]
stores = ["foo", "bar", "baz"]
n = 30

product_list = [products[i] for i in np.random.randint(0, len(products), n)]
store_list = [stores[i] for i in np.random.randint(0, len(stores), n)]
rating_list = np.random.random(n) * 5
sales_list = np.random.random(n) * 10000

df = pd.DataFrame(
    'store': store_list, 
     'product': product_list, 
     'sales': sales_list, 
     'rating': rating_list)

df = df[['store', 'product', 'sales', 'rating']]

df[:5]

我想按storeproduct 以及sumcountsales 分组,同时使用ratingmean

这很简单:

dfg = df.groupby(['store', 'product']).agg('sales': ['sum', 'count'], 
                                            'rating': 'mean')

现在,我只想保留每组中评分最高的两个行。我可以得到这个如下(使用来自1的有点不直观的[对我]咒语的多级扩展):

g = dfg[('rating', 'mean')].groupby(
      level=0, group_keys=False).apply(
        lambda x: x.sort_values(ascending=False).head(2))
g

这将返回以下Series

store  product
bar    B          3.601135
       A          1.867449
baz    B          2.984196
       D          2.780500
foo    B          3.767912
       D          3.129346
Name: (rating, mean), dtype: float64

但我丢失了 ('sales', 'sum')('sales', 'count') 列。

我怀疑我需要提取 g.index 并以某种方式使用它,但无法对其进行排序(双关语)。

编辑:下面的答案设法给了我正在寻找的组,但我真正想要的是一种稳定的排序,我不仅可以获得每个组中的前 N ​​个平均评分,而且组本身排序后,第一组的评分最高,等等。在某种程度上,这只是锦上添花,因为我现在拥有我想要的值,并且希望报告更漂亮。

【问题讨论】:

赞成双关语。 【参考方案1】:

我已经整理好了。我需要将sort_values 应用于未索引的DataFrame,而不是索引分组表并执行后续的groupbysort_values,并明确指定要排序的列:

g = dfg.groupby(level=0, group_keys=False).apply(
      lambda x: x.sort_values(('rating', 'mean'), ascending=False).head(2))

给我想要的结果:

【讨论】:

啊,抱歉,我发帖时没有看到您发布答案。我要删除吗?【参考方案2】:

这就是你的做法,使用sort_values + groupby + head -

dfg.sort_values(('rating', 'mean'), ascending=False)\
   .groupby(level=0)\
   .head(2)\
   .sort_index()

                 rating         sales      
                   mean           sum count
store product                              
bar   B        4.388521    636.813757     1
      C        3.931341   1843.772878     1
baz   A        2.501077  23110.162196     4
      B        3.339784  10610.257660     2
foo   B        2.785306  10315.968161     2
      D        2.160556  31084.181719     5

最后的sort_index 调用解决了索引乱序问题(双关语)。

【讨论】:

对 - 我已经做到了,但没有维护组。应该提到它。 @sfjac 抱歉,忘记在 ;) 中添加重要部分 @sfjac 或.sort_index(ascending=[True, False]),如果您想更好地控制每个级别的单独排序方式。 @sfjac 嗯,sort_index 对索引进行排序,但不关心评分的顺序。最后, groupby + apply + sort_values 可能更合适...... :( @sfjac 编辑,没关系,只是注意到它和你的一模一样。抱歉,我仍然不确定您的预期输出是什么以及您当前的输出如何不正确...请您帮我更好地理解吗?

以上是关于Pandas groupby 在保留多个聚合的组内排序的主要内容,如果未能解决你的问题,请参考以下文章

具有多个聚合的 pyspark groupBy(如 pandas)

如何在 Pandas 的组内使用 cumsum?

Python/Pandas - 结合 groupby 平均值和最小值

Groupby并在pandas中执行多个函数的聚合

将 pandas GroupBy 中的多个列值聚合为 dict

pandas编写自定义函数计算多个数据列的加和(sum)使用groupby函数和apply函数聚合计算分组内多个数据列的加和