Pandas按组进行分组排序,保留多个聚合结果。
Pandas按组进行分组排序,保留多个聚合结果。
我想在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]
我想按store
和product
进行分组,并对sales
进行sum
和count
,同时对rating
进行mean
。
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名,而且组本身也按照评分排序,使得第一组具有最高评分,依此类推。在某种程度上,这只是锦上添花,因为我现在已经有了所需的值,只是希望报告更漂亮一些。
Pandas中的groupby操作可以对数据进行分组,并对每个组进行聚合操作。然而,有时候在每个组内部进行排序,并保留多个聚合结果是一个常见的需求。本文将介绍一个解决这个问题的方法。
在上述代码中,通过使用sort_values函数对数据进行排序,参数('rating', 'mean')表示按照rating列的mean值进行降序排序。然后使用groupby(level=0)对数据进行分组,level=0表示按照第一层索引进行分组。接着使用head(2)函数保留每个组的前两个数据。最后使用sort_index函数对数据进行排序,以解决索引排序不正确的问题。
这种方法可以保留每个组内部的排序,并且可以同时保留多个聚合结果。通过在groupby之前进行排序,可以确保分组后的数据按照指定的排序顺序进行聚合操作。
如果想要更精细地控制每个层级的排序顺序,可以使用sort_index函数的ascending参数。例如,使用sort_index(ascending=[True, False])可以对第一层索引按升序排序,对第二层索引按降序排序。
在讨论中还提到了另一种解决方法,即使用groupby + apply + sort_values的组合。这种方法可以在每个组内部使用apply函数对数据进行排序,并且可以更好地控制排序的方式。
总结一下,Pandas中的groupby操作可以实现对数据进行分组和聚合,但是有时候需要在每个组内部进行排序并保留多个聚合结果。通过使用sort_values + groupby + head + sort_index的组合,可以实现这个需求。另外,还可以使用groupby + apply + sort_values的方式进行解决。
问题的出现原因是在对分组后的表格进行排序时,原作者使用了错误的方法。他在对分组后的表格进行索引和排序时,并没有得到期望的结果。解决方法是对未进行索引的DataFrame应用排序操作,并明确指定排序的列。
具体的解决方法是使用groupby
函数对DataFrame进行分组,然后对每个分组应用sort_values
函数进行排序。最后,使用head
函数选取每个分组中的前两行。
以下是正确的代码:
g = dfg.groupby(level=0, group_keys=False).apply( lambda x: x.sort_values(('rating', 'mean'), ascending=False).head(2))
这样就可以得到期望的结果。
解决方法来源于原作者的回答,他在回答中提到了这个错误,并给出了正确的解决方法。