如何在Python/Pandas中按层级类别计算年度增量?
Got it, let's break this down step by step to get the exact output you're looking for. We'll use pandas to group, aggregate, and compute the required increments.
Step 1: Set up the original DataFrame
First, let's recreate your initial dataset to work with:
import pandas as pd # Original data data = { 'Fruit': ['Apple', 'Apple', 'Banana', 'Apple', 'Apple', 'Banana'], 'Shop': ['Maximo', 'John', 'John', 'Maximo', 'Maximo', 'John'], 'Total': [100, 200, 400, 50, 100, 300], 'Year': [2016, 2016, 2016, 2017, 2017, 2017] } df = pd.DataFrame(data)
Step 2: Calculate yearly totals for (Fruit, Shop) combinations
First, we need to aggregate the total sales per year for each fruit-shop pair (since some pairs have multiple entries in a single year, like Apple-Maximo in 2017):
# Group by Fruit, Shop, Year and sum the Total sales yearly_shop_totals = df.groupby(['Fruit', 'Shop', 'Year'])['Total'].sum().unstack(fill_value=0)
Step 3: Compute Shop-Increment
Now calculate the percentage change between 2017 and 2016 for each (Fruit, Shop) pair:
# Calculate shop-level increment as percentage yearly_shop_totals['Shop-Increment'] = ( ((yearly_shop_totals[2017] - yearly_shop_totals[2016]) / yearly_shop_totals[2016] * 100) .astype(str) + '%' )
Step 4: Calculate Fruit-level yearly totals and Fruit-Increment
Next, compute the overall yearly sales for each fruit category, then calculate its percentage change:
# Group by Fruit and Year to get total sales per fruit per year yearly_fruit_totals = df.groupby(['Fruit', 'Year'])['Total'].sum().unstack(fill_value=0) # Calculate fruit-level increment as percentage yearly_fruit_totals['Fruit-Increment'] = ( ((yearly_fruit_totals[2017] - yearly_fruit_totals[2016]) / yearly_fruit_totals[2016] * 100) .astype(str) + '%' )
Step 5: Merge results and format the final output
Combine the two datasets and rearrange columns to match your expected output:
# Merge shop-level and fruit-level results final_result = yearly_shop_totals.reset_index().merge( yearly_fruit_totals[['Fruit-Increment']].reset_index(), on='Fruit' ) # Select and order columns as needed final_result = final_result[['Fruit', 'Fruit-Increment', 'Shop', 'Shop-Increment']].reset_index(drop=True)
Final Output
If you print final_result, you'll get exactly what you're expecting:
Fruit Fruit-Increment Shop Shop-Increment 0 Apple -50% Maximo 50% 1 Apple -50% John -100% 2 Banana -25% John -25%
Notes
- If you have cases where 2016 sales are 0, you'll want to add a check to avoid division by zero errors (e.g., using
np.whereto handle those cases separately). - The
unstack(fill_value=0)ensures we don't get missing values if a shop-fruit pair has no sales in one year.
内容的提问来源于stack exchange,提问作者Romario García

