我有一个这样的数据集(示例目的)
df = pd.DataFrame({
'Store' : [100, 100, 100, 100, 101, 101, 101, 101],
'Product' : [5, 3, 10, 1, 3, 11, 2, 5],
'Category' : ['A', 'B', 'C', 'A', 'B', 'A', 'C', 'A'],
'Sales' : [100, 235, 120, 56, 789, 230, 300, 35]
})
原来是这样
Store Product Category Sales
100 5 A 100
100 3 B 235
100 10 C 120
100 1 A 56
101 3 B 789
101 11 A 230
101 2 C 300
101 5 A 35
每个商店都有一些产品,每个产品都有一些类别。我需要找出每家商店的总销售额以及每家商店中每个类别的销售额百分比。所以结果必须是这样的:
total_Sales Category_A Category_B Category_C
Store
100 511 30.528376 45.988258 23.483366
101 1354 19.571640 58.271787 22.156573
(类别列以 % 为单位)
目前我是这样做的:
df1 = df.groupby(['Store']).apply(lambda x: x['Sales'].sum())
df1 = df1.to_frame()
df1 = df1.rename(columns={0 : 'Sales'})
def category_util(x, col, cat):
total_sales = x['Sales'].sum()
cat_sales = x[x[col] == cat]['Sales'].sum()
if cat_sales == 0:
return 0
else:
return cat_sales*100/total_sales
df1['Category_A'] = df.groupby(['Store']).apply(lambda x: category_util(x, 'Category', 'A'))
df1['Category_B'] = df.groupby(['Store']).apply(lambda x: category_util(x, 'Category', 'B'))
df1['Category_C'] = df.groupby(['Store']).apply(lambda x: category_util(x, 'Category', 'C'))
df1
是所需的输出。它工作正常,但每个 apply
函数都一次又一次地对分组列进行排序,对于大型数据集,非常耗时。我想在一个函数调用中做到这一点。我试过类似的东西:
df.groupby(['Store']).agg([lambda x: category_util(x, 'Category', 'A'),
lambda x: category_util(x, 'Category', 'B'),
lambda x: category_util(x, 'Category', 'C')])
但它失败了 KeyError
为“销售”
pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_value()
pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_value()
pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()
pandas/_libs/index_class_helper.pxi in pandas._libs.index.Int64Engine._check_type()
KeyError: 'Sales'
有什么解决办法吗?有没有办法将 apply
函数与一组 lambda 函数一起使用并一次性计算所有列?如果用 apply
不行,用 agg
可以吗?这真的会为我节省很多时间。提前致谢。
答案 0 :(得分:2)
您可以使用 pivot_table
和 unstack
table = df.pivot_table(index=['Store', 'Category'], values=['Sales'], aggfunc='sum')#.unstack().add_prefix('Category_')
t_sales = table.sum(level=0)
table=table.div(table.sum(level=0)).mul(100).unstack().add_prefix('Category_')
table.assign(total_sales=t_sales).reset_index()
Store Category_Sales total_sales
Category Category_A Category_B Category_C
0 100 30.528376 45.988258 23.483366 511
1 101 19.571640 58.271787 22.156573 1354
答案 1 :(得分:2)
我们可以将 groupby
与 unstack
一起使用。然后我们将总和除以 axis=1
:
dfn = df.groupby(['Store', 'Category'])['Sales'].sum().unstack(level=1)
total_sales = dfn.sum(axis=1)
dfn = (
dfn.div(total_sales, axis=0)
.mul(100)
.add_prefix("Category_")
.assign(total_sales=total_sales)
).rename_axis(columns=None)
Category_A Category_B Category_C total_sales
Store
100 30.528376 45.988258 23.483366 511
101 19.571640 58.271787 22.156573 1354
答案 2 :(得分:2)
我们可以创建两个 groupby 对象(相对便宜的操作),并通过管道返回一个包含总和和百分比的数据帧的函数:
group1 = df.groupby('Store')
group2 = df.groupby(['Store', 'Category'])
(df.assign(total_sales = group1.Sales.transform('sum'))
.groupby(['Store','Category'])
.pipe(lambda df: pd.DataFrame({"res" :df.Sales.sum()
.div(df.total_sales.max())
.mul(100),
"total_sales": df.total_sales.max()}))
.set_index('total_sales', append = True)
.unstack('Category')
.droplevel(0, axis=1)
.add_prefix('Category_')
.rename_axis(columns=None)
.reset_index()
)
Store total_sales Category_A Category_B Category_C
0 100 511 30.528376 45.988258 23.483366
1 101 1354 19.571640 58.271787 22.156573