Pandas groupby apply function with array of functions
Pandas groupby apply function with an array of functions
我有一个这样的数据集(示例目的)
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
for 'Sales`
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_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
我们可以使用 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
我们可以创建两个 groupby 对象(相对便宜的操作),并通过管道传递一个 returns 数据帧的函数,包含总和和百分比:
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
我有一个这样的数据集(示例目的)
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
for 'Sales`
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_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
我们可以使用 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
我们可以创建两个 groupby 对象(相对便宜的操作),并通过管道传递一个 returns 数据帧的函数,包含总和和百分比:
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