如何根据索引条件对列的行求和以创建 % of group 列?

How can I sum rows of a column based on an index condition to create a % of group column?

我有以下 Pandas DataFrame:

# Create DataFrame
import pandas as pd
data = {'Menu Category': ['Appetizers', 'Appetizers', 'Appetizers', 'Mains', 'Mains', 
        'Mains', 'Desserts', 'Desserts', 'Desserts'], 
        'Menu Item': ['Fries', 'Poppers', 'Wings', 'Pasta', 'Burger', 'Pizza', 
                      'Ice Cream', 'Cake', 'Fruit'],
        'Sales Quantity': [100, 50, 40, 200, 400, 250, 100, 120, 50],
       }
df = pd.DataFrame(data)
df

我想添加两列。 1) 显示每个项目所代表的菜单的百分比数量(整个菜单是此数据集),以及 2) 显示项目所属的菜单类别的百分比数量(例如 Sale Quantity 的百分比Fries代表Appetizers组,即(100/190) * 100).

我知道如何获取提到的第一列:

# Add % Quantity of Menu Column
percent_menu_qty = []
for i in df['Sales Quantity']:
    i = round(i/df['Sales Quantity'].sum() * 100, 2)
    percent_menu_qty.append(i)
df['% Quantity of Menu'] = percent_menu_qty
df

我不知道该怎么做的是第二个。我尝试将 Menu Category 设置为索引并执行以下操作:

# Add % Quantity of Menu Category Column
df = df.set_index('Menu Category')

lst = []
for index, x in df['Sales Quantity'].iteritems():
    if index == 'Appetizers':
        x = x/sum(x)
        lst.append(x)
    elif index == 'Mains':
        x = x/sum(x)
        lst.append(x)
    elif index == 'Desserts':
        x =x/sum(x)
        lst.append(x)
lst

我知道我需要以某种方式为每个 Menu Category 设置一个条件,如果 index == 'a certain menu category value' 然后将数量除以该菜单类别的总和。到目前为止我还没有弄明白。

我认为您正在寻找 groupby + 变换 sum 以获得“类别”总和;然后将每个“销售数量”除以它们的“类别”总和。这为我们提供了每个菜单项在其菜单类别中的份额。

您还可以对第一列使用向量化 div 方法而不是循环:

df['%Qty of Menu'] = df['Sales Quantity'].div(df['Sales Quantity'].sum()).mul(100).round(2)
df['%Qty of Menu Cat'] = df.groupby('Menu Category')['Sales Quantity'].transform('sum').rdiv(df['Sales Quantity']).mul(100).round(2)

输出:

  Menu Category  Menu Item  Sales Quantity  %Qty of Menu  %Qty of Menu Cat
0    Appetizers      Fries             100          7.63             52.63
1    Appetizers    Poppers              50          3.82             26.32
2    Appetizers      Wings              40          3.05             21.05
3         Mains      Pasta             200         15.27             23.53
4         Mains     Burger             400         30.53             47.06
5         Mains      Pizza             250         19.08             29.41
6      Desserts  Ice Cream             100          7.63             37.04
7      Desserts       Cake             120          9.16             44.44
8      Desserts      Fruit              50          3.82             18.52

首先要表扬你使用全面的逐行。我仍然时不时地使用它们,因为我认为循环更容易让其他人在没有代码本身的情况下阅读和理解原理是什么。运行。

可是呀。对于这个解决方案,我创建了一对单衬垫,让我解释一下每一个衬垫是什么。

df['% Quantity of Menu'] = ((df['Sales Quantity']/df['Sales Quantity'].sum())*100).round(2)

对于您的第一个问题,不是逐行循环,而是将列值除以标量值(即列 df['Sales Quantity'].sum() 的总和),然后将比率乘以 100 得到百分比, 然后四舍五入到小数点后两位。

df['%Qty of Menu Category'] = ((df['Sales Quantity']/df.groupby(['Menu Category'])['Sales Quantity'].transform('sum'))*100).round(2)

因此,对于第二个问题,我们需要将列值除以每个对应类别的总和,而不是整个列。因此,我们通过 groupby 为每个类别 df.groupby(['Menu Category'])['Sales Quantity'].transform('sum') 获取值,然后通过替换代码部分来执行与第一个相同的操作。 这里,为什么我们用df.groupby(['Menu Category'])['Sales Quantity'].transform('sum')而不是df.groupby(['Menu Category'])['Sales Quantity'].sum()呢?因为可以使用标量或具有相同维度的序列来完成级数的划分,而前一种方法给出了相同维度的级数。

df['Sales Quantity']
0    100
1     50
2     40
3    200
4    400
5    250
6    100
7    120
8     50
Name: Sales Quantity, dtype: int64

df.groupby(['Menu Category'])['Sales Quantity'].transform('sum')
0    190
1    190
2    190
3    850
4    850
5    850
6    270
7    270
8    270
Name: Sales Quantity, dtype: int64

df.groupby(['Menu Category'])['Sales Quantity'].sum()
Menu Category
Appetizers    190
Desserts      270
Mains         850
Name: Sales Quantity, dtype: int64