Python 使用函数数组创建groupby apply函数
我有一个类似于此示例的数据集Python 使用函数数组创建groupby apply函数,python,pandas,group-by,data-science,feature-engineering,Python,Pandas,Group By,Data Science,Feature Engineering,我有一个类似于此示例的数据集 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] })
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'))
类别列的单位为%
目前我是这样做的:
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')])
但它失败了,出现了“销售”的关键错误`
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?这真的会节省我很多时间。提前谢谢。您可以使用pivot\u table和unstack
您可以使用pivot_table和unstack
我们可以使用带有unstack的groupby。然后我们将总和除以轴=1:
我们可以使用带有unstack的groupby。然后我们将总和除以轴=1:
我们可以创建两个相对便宜的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
我们可以创建两个相对便宜的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
非常感谢你。这确实是最好的解决方案。非常感谢。这确实是最好的解决方案。
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