Groupby 和 Value Counting 类别
Groupby and Value Counting categories
我有一个数据框,其中每一行代表产品销售。这些链接到订单号(可以有多个产品),每个都有价格和颜色。我需要按订单号对这些进行分组,并获得一个列来计算该订单行的每种产品类型。
df = pd.DataFrame({'Product': ['X','X','Y','X','Y','W','W','Z','W','X'],
'Order #': ['01','01','02','03','03','03','04','05','05','05'],
'Price': [100,100,650,50,700,3000,2500,10,2500,150],
'Color': ['RED','BLUE','RED','RED','BLUE','GREEN','RED','BLUE','BLUE','GREEN']})
'regular' 使用计数的分组表达式不是我要找的。
# Aggregate
ag_func = {'Product Quant.': pd.NamedAgg(column='Product', aggfunc='count'),
'Total Price': pd.NamedAgg(column='Price', aggfunc='sum'),
'Color Quant.': pd.NamedAgg(column='Color', aggfunc='count')}
# Test
test = df.groupby(pd.Grouper(key='Order #')).agg(**ag_func).reset_index()
我可以通过对每个类别(产品/颜色)使用 get_dummies 然后使用 sum 聚合函数来解决这个问题。这对于较小的数据集来说很好,但在我的真实世界中有几十个类别,并且新的集合一起出现在不同的类别中......
这是我想出的'solution'
# Dummy
df_dummy = pd.get_dummies(df, prefix='Type', prefix_sep=': ', columns=['Product', 'Color'])
ag_func2 = {'Product Quant.': pd.NamedAgg(column='Order #', aggfunc='count'),
'W total': pd.NamedAgg(column='Type: W', aggfunc='sum'),
'X total': pd.NamedAgg(column='Type: X', aggfunc='sum'),
'Y total': pd.NamedAgg(column='Type: Y', aggfunc='sum'),
'Z total': pd.NamedAgg(column='Type: Z', aggfunc='sum'),
'Total Price': pd.NamedAgg(column='Price', aggfunc='sum'),
'Color BLUE': pd.NamedAgg(column='Type: BLUE', aggfunc='sum'),
'Color GREEN': pd.NamedAgg(column='Type: GREEN', aggfunc='sum'),
'Color RED': pd.NamedAgg(column='Type: RED', aggfunc='sum')}
solution = df_dummy.groupby(pd.Grouper(key='Order #')).agg(**ag_func2).reset_index()
注意第 1 行的 2 个 X 产品和第 5 行的 2 个蓝色产品。这种行为是我所需要的,但这对于在多个数据集上重复使用来说太复杂了。我尝试使用 pivot_tables 但没有成功。
我是否应该只定义一个函数来遍历分类列,虚拟化这些列,然后使用虚拟变量的总和聚合按一组列分组?
谢谢
IIUC 你的问题是为所有创建的假人输入所有 pd.NamedAgg
,也许你可以单独进行操作。先创建组对象,然后concat
对不同的列进行不同的操作
gr = df.groupby('Order #')
res = pd.concat([
# equivalent to count the orders
gr.size().to_frame(name='Product Quant.'),
# equivalent to dummy then sum the dummy product columns
gr['Product'].value_counts().unstack(fill_value=0).add_suffix(' Total'),
# sum the price to get the total
gr['Price'].sum().to_frame(name='Total Price'),
# equivalent to sum the dummy color columns
gr['Color'].value_counts().unstack(fill_value=0).add_prefix('Color ')
], axis=1)
print(res)
Product Quant. W Total X Total Y Total Z Total Total Price \
Order #
01 2 0 2 0 0 200
02 1 0 0 1 0 650
03 3 1 1 1 0 3750
04 1 1 0 0 0 2500
05 3 1 1 0 1 2660
Color BLUE Color GREEN Color RED
Order #
01 1 0 1
02 0 0 1
03 1 1 1
04 0 0 1
05 2 1 0
所以基本上在这种情况下,groupby.value_counts.unstack
等同于 get_dummies.groupby.sum
。
为了进一步使用,而不是
df.groupby('Order #')['Product'].value_counts().unstack(fill_value=0)
您可以执行 pivot_table
以获得相同的结果:
df.pivot_table(index='Order #', columns='Product', aggfunc='size', fill_value=0)
我有一个数据框,其中每一行代表产品销售。这些链接到订单号(可以有多个产品),每个都有价格和颜色。我需要按订单号对这些进行分组,并获得一个列来计算该订单行的每种产品类型。
df = pd.DataFrame({'Product': ['X','X','Y','X','Y','W','W','Z','W','X'],
'Order #': ['01','01','02','03','03','03','04','05','05','05'],
'Price': [100,100,650,50,700,3000,2500,10,2500,150],
'Color': ['RED','BLUE','RED','RED','BLUE','GREEN','RED','BLUE','BLUE','GREEN']})
'regular' 使用计数的分组表达式不是我要找的。
# Aggregate
ag_func = {'Product Quant.': pd.NamedAgg(column='Product', aggfunc='count'),
'Total Price': pd.NamedAgg(column='Price', aggfunc='sum'),
'Color Quant.': pd.NamedAgg(column='Color', aggfunc='count')}
# Test
test = df.groupby(pd.Grouper(key='Order #')).agg(**ag_func).reset_index()
我可以通过对每个类别(产品/颜色)使用 get_dummies 然后使用 sum 聚合函数来解决这个问题。这对于较小的数据集来说很好,但在我的真实世界中有几十个类别,并且新的集合一起出现在不同的类别中......
这是我想出的'solution'
# Dummy
df_dummy = pd.get_dummies(df, prefix='Type', prefix_sep=': ', columns=['Product', 'Color'])
ag_func2 = {'Product Quant.': pd.NamedAgg(column='Order #', aggfunc='count'),
'W total': pd.NamedAgg(column='Type: W', aggfunc='sum'),
'X total': pd.NamedAgg(column='Type: X', aggfunc='sum'),
'Y total': pd.NamedAgg(column='Type: Y', aggfunc='sum'),
'Z total': pd.NamedAgg(column='Type: Z', aggfunc='sum'),
'Total Price': pd.NamedAgg(column='Price', aggfunc='sum'),
'Color BLUE': pd.NamedAgg(column='Type: BLUE', aggfunc='sum'),
'Color GREEN': pd.NamedAgg(column='Type: GREEN', aggfunc='sum'),
'Color RED': pd.NamedAgg(column='Type: RED', aggfunc='sum')}
solution = df_dummy.groupby(pd.Grouper(key='Order #')).agg(**ag_func2).reset_index()
注意第 1 行的 2 个 X 产品和第 5 行的 2 个蓝色产品。这种行为是我所需要的,但这对于在多个数据集上重复使用来说太复杂了。我尝试使用 pivot_tables 但没有成功。
我是否应该只定义一个函数来遍历分类列,虚拟化这些列,然后使用虚拟变量的总和聚合按一组列分组?
谢谢
IIUC 你的问题是为所有创建的假人输入所有 pd.NamedAgg
,也许你可以单独进行操作。先创建组对象,然后concat
对不同的列进行不同的操作
gr = df.groupby('Order #')
res = pd.concat([
# equivalent to count the orders
gr.size().to_frame(name='Product Quant.'),
# equivalent to dummy then sum the dummy product columns
gr['Product'].value_counts().unstack(fill_value=0).add_suffix(' Total'),
# sum the price to get the total
gr['Price'].sum().to_frame(name='Total Price'),
# equivalent to sum the dummy color columns
gr['Color'].value_counts().unstack(fill_value=0).add_prefix('Color ')
], axis=1)
print(res)
Product Quant. W Total X Total Y Total Z Total Total Price \
Order #
01 2 0 2 0 0 200
02 1 0 0 1 0 650
03 3 1 1 1 0 3750
04 1 1 0 0 0 2500
05 3 1 1 0 1 2660
Color BLUE Color GREEN Color RED
Order #
01 1 0 1
02 0 0 1
03 1 1 1
04 0 0 1
05 2 1 0
所以基本上在这种情况下,groupby.value_counts.unstack
等同于 get_dummies.groupby.sum
。
为了进一步使用,而不是
df.groupby('Order #')['Product'].value_counts().unstack(fill_value=0)
您可以执行 pivot_table
以获得相同的结果:
df.pivot_table(index='Order #', columns='Product', aggfunc='size', fill_value=0)