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

sfj*_*jac 5 python sorting pandas pandas-groupby

我想在由 返回的组中应用排序和限制groupby,就像在这个问题中一样。但是,我有多个聚合,我希望所有聚合都保留在结果中。

这是一个简单的例子:

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]
Run Code Online (Sandbox Code Playgroud)

未分组的数据框

我想通过storeandproduct和 bothsumcountthe分组sales,同时mean使用rating.

这很简单:

dfg = df.groupby(['store', 'product']).agg({'sales': ['sum', 'count'], 
                                            'rating': 'mean'})
Run Code Online (Sandbox Code Playgroud)

分组

现在,我只想保留每组中评分最高的两个行。我能得到这个如下(使用有些直观的多层次扩展[我]咒语从1):

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

这将返回以下内容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
Run Code Online (Sandbox Code Playgroud)

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

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

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

sfj*_*jac 5

我整理好了 我需要将 应用于un-indexed ,而不是索引分组表并执行后续groupbysort_values上述操作,并明确指定要排序的列:sort_valuesDataFrame

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

给我想要的结果:

在此处输入图片说明