我想在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]
我希望按store
和product
以及sum
和count
sales
分组,同时取mean
的{{1}} rating
。
这很简单:
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个平均评分,但是这些团体本身的排序是为了让第一组获得最高等级,等等。在某种程度上,这只是锦上添花,因为我现在拥有我想要的价值,并希望报告更漂亮。
答案 0 :(得分:2)
我已经对它进行了分类。我没有将分组表编入索引并执行上述后续groupby
和sort_values
,而是将sort_values
应用于未编入索引的DataFrame
,指定要排序的列明确地说:
g = dfg.groupby(level=0, group_keys=False).apply(
lambda x: x.sort_values(('rating', 'mean'), ascending=False).head(2))
给我想要的结果:
答案 1 :(得分: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
调用会排除索引无序问题(双关语)。