Pandas GroupBy Operations (groupby)
groupbyIt is one of Pandas' most powerful features, allowing you to group data by one or more columns, and then perform aggregation, transformation, or filtering operations on each group.
groupby Basic Usage
Grouping by a Single Column
Example
import pandas as pd
# Create sample data
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations", "Sales", "Technology"],
"Name": ["Zhang San", "Li Si", "Wang Wu", "Zhao Liu", "Qian Qi", "Sun Ba"],
"Salary": [12000, 15000, 11000, 18000, 14000, 13000]
})
print("Original data:")
print(df)
print()
# Group by department
grouped = df.groupby("Department")
print(f"Grouped object: {type(grouped)}")
print(f"Number of groups: {len(grouped)}")
print()
# View the groups
print("Data for each group:")
for name, group in grouped:
print(f"\nDepartment: {name}")
print(group)
# Create sample data
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations", "Sales", "Technology"],
"Name": ["Zhang San", "Li Si", "Wang Wu", "Zhao Liu", "Qian Qi", "Sun Ba"],
"Salary": [12000, 15000, 11000, 18000, 14000, 13000]
})
print("Original data:")
print(df)
print()
# Group by department
grouped = df.groupby("Department")
print(f"Grouped object: {type(grouped)}")
print(f"Number of groups: {len(grouped)}")
print()
# View the groups
print("Data for each group:")
for name, group in grouped:
print(f"\nDepartment: {name}")
print(group)
Grouping and Aggregating
Example
import pandas as pd
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations", "Sales"],
"Salary": [12000, 15000, 11000, 18000, 14000]
})
print("Average salary by department:")
print(df.groupby("Department")["Salary"].mean())
print()
print("Sum by department:")
print(df.groupby("Department")["Salary"].sum())
print()
print("Count by department:")
print(df.groupby("Department").size())
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations", "Sales"],
"Salary": [12000, 15000, 11000, 18000, 14000]
})
print("Average salary by department:")
print(df.groupby("Department")["Salary"].mean())
print()
print("Sum by department:")
print(df.groupby("Department")["Salary"].sum())
print()
print("Count by department:")
print(df.groupby("Department").size())
Grouping by Multiple Columns
Example
import pandas as pd
df = pd.DataFrame({
"Year": ["2023", "2023", "2024", "2024"],
"Department": ["Technology", "Sales", "Technology", "Sales"],
"Salary": [12000, 15000, 13000, 16000]
})
print("Group by year and department:")
print(df.groupby(["Year", "Department"])["Salary"].sum())
print()
# Output as DataFrame
result = df.groupby(["Year", "Department"]).agg({
"Salary": "sum"
}).reset_index()
print("Result DataFrame:")
print(result)
df = pd.DataFrame({
"Year": ["2023", "2023", "2024", "2024"],
"Department": ["Technology", "Sales", "Technology", "Sales"],
"Salary": [12000, 15000, 13000, 16000]
})
print("Group by year and department:")
print(df.groupby(["Year", "Department"])["Salary"].sum())
print()
# Output as DataFrame
result = df.groupby(["Year", "Department"]).agg({
"Salary": "sum"
}).reset_index()
print("Result DataFrame:")
print(result)
Common Aggregation Functions
Single Aggregation
| Function | Description |
|---|---|
sum() |
Sum |
mean() |
Mean |
median() |
Median |
std() |
Standard deviation |
min() / max() |
Min/Max |
count() |
Count |
first() / last() |
First/Last value |
Example
import pandas as pd
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations"],
"Salary": [12000, 15000, 11000, 18000]
})
# Chain multiple aggregations
print("Chained aggregation:")
print(df.groupby("Department")["Salary"].agg(["sum", "mean", "max", "min"]))
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations"],
"Salary": [12000, 15000, 11000, 18000]
})
# Chain multiple aggregations
print("Chained aggregation:")
print(df.groupby("Department")["Salary"].agg(["sum", "mean", "max", "min"]))
Custom Aggregation
Example
import pandas as pd
import numpy as np
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations"],
"Salary": [12000, 15000, 11000, 18000]
})
# Custom aggregation function
def range_func(x):
return x.max() - x.min()
print("Using a custom function:")
print(df.groupby("Department")["Salary"].agg(range_func))
print()
# Named aggregation (recommended)
print("Named aggregation:")
print(df.groupby("Department").agg(
Minimum salary=("Salary", "min"),
Maximum salary=("Salary", "max"),
Average salary=("Salary", "mean")
))
import numpy as np
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations"],
"Salary": [12000, 15000, 11000, 18000]
})
# Custom aggregation function
def range_func(x):
return x.max() - x.min()
print("Using a custom function:")
print(df.groupby("Department")["Salary"].agg(range_func))
print()
# Named aggregation (recommended)
print("Named aggregation:")
print(df.groupby("Department").agg(
Minimum salary=("Salary", "min"),
Maximum salary=("Salary", "max"),
Average salary=("Salary", "mean")
))
transform
transform can calculate on each group while keeping the original data shape, and return a result with the same shape as the original data.
Example
import pandas as pd
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations", "Sales"],
"Salary": [12000, 15000, 11000, 18000, 14000]
})
print("Original data:")
print(df)
print()
# Calculate the average salary for each department and broadcast it to each row
df["Department average salary"] = df.groupby("Department")["Salary"].transform("mean")
print("After adding department average salary:")
print(df)
print()
# Calculate each person's salary as a percentage of the department
df["Salary percentage"] = df["Salary"] / df["Department average salary"]
print("Salary proportion:")
print(df)
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations", "Sales"],
"Salary": [12000, 15000, 11000, 18000, 14000]
})
print("Original data:")
print(df)
print()
# Calculate the average salary for each department and broadcast it to each row
df["Department average salary"] = df.groupby("Department")["Salary"].transform("mean")
print("After adding department average salary:")
print(df)
print()
# Calculate each person's salary as a percentage of the department
df["Salary percentage"] = df["Salary"] / df["Department average salary"]
print("Salary proportion:")
print(df)
filter Filtering
filter can filter data based on group conditions.
Example
import pandas as pd
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations", "Sales", "Technology"],
"Salary": [12000, 15000, 11000, 18000, 14000, 13000]
})
print("Original data:")
print(df)
print()
# Filter departments whose average salary is greater than 13000
print("Department average salary > 13000:")
filtered = df.groupby("Department").filter(lambda x: x["Salary"].mean() > 13000)
print(filtered)
print()
# Filter groups with count greater than 2
print("Number of members > 2:")
filtered2 = df.groupby("Department").filter(lambda x: len(x) > 2)
print(filtered2)
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations", "Sales", "Technology"],
"Salary": [12000, 15000, 11000, 18000, 14000, 13000]
})
print("Original data:")
print(df)
print()
# Filter departments whose average salary is greater than 13000
print("Department average salary > 13000:")
filtered = df.groupby("Department").filter(lambda x: x["Salary"].mean() > 13000)
print(filtered)
print()
# Filter groups with count greater than 2
print("Number of members > 2:")
filtered2 = df.groupby("Department").filter(lambda x: len(x) > 2)
print(filtered2)
apply Custom Functions
apply allows applying custom functions to each group.
Example
import pandas as pd
import numpy as np
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations"],
"Salary": [12000, 15000, 11000, 18000]
})
# Apply a custom function to each group
result = df.groupby("Department").apply(
lambda x: pd.Series({
"Sum": x["Salary"].sum(),
"Mean": x["Salary"].mean()
})
)
print("Custom aggregation result:")
print(result)
import numpy as np
df = pd.DataFrame({
"Department": ["Technology", "Sales", "Technology", "Operations"],
"Salary": [12000, 15000, 11000, 18000]
})
# Apply a custom function to each group
result = df.groupby("Department").apply(
lambda x: pd.Series({
"Sum": x["Salary"].sum(),
"Mean": x["Salary"].mean()
})
)
print("Custom aggregation result:")
print(result)
Hands-on: Sales Data Analysis
Example
import pandas as pd
# Simulate sales data
sales = pd.DataFrame({
"Date": pd.date_range("2024-01-01", periods=30, freq="D"),
"Product": ["Mobile", "Computer", "Tablet"] * 10,
"Channel": ["Online"] * 15 + ["Offline"] * 15,
"Sales amount": [1000, 2000, 1500] * 10
})
print("=== Sales Data Analysis ===\n")
# 1. Statistics by product
print("1. Statistics by product:")
product_summary = sales.groupby("Product")["Sales amount"].agg(["sum", "mean", "count"])
print(product_summary)
print()
# 2. Statistics by channel
print("2. Statistics by channel:")
channel_summary = sales.groupby("Channel")["Sales amount"].sum()
print(channel_summary)
print()
# 3. Cross statistics by product and channel
print("3. Product × Channel cross statistics:")
cross_summary = sales.groupby(["Product", "Channel"])["Sales amount"].sum().unstack()
print(cross_summary)
print()
# 4. Calculate the proportion of sales for each product
print("4. Sales proportion:")
total = sales["Sales amount"].sum()
product_pct = sales.groupby("Product")["Sales amount"].sum() / total * 100
print(product_pct.round(2))
# Simulate sales data
sales = pd.DataFrame({
"Date": pd.date_range("2024-01-01", periods=30, freq="D"),
"Product": ["Mobile", "Computer", "Tablet"] * 10,
"Channel": ["Online"] * 15 + ["Offline"] * 15,
"Sales amount": [1000, 2000, 1500] * 10
})
print("=== Sales Data Analysis ===\n")
# 1. Statistics by product
print("1. Statistics by product:")
product_summary = sales.groupby("Product")["Sales amount"].agg(["sum", "mean", "count"])
print(product_summary)
print()
# 2. Statistics by channel
print("2. Statistics by channel:")
channel_summary = sales.groupby("Channel")["Sales amount"].sum()
print(channel_summary)
print()
# 3. Cross statistics by product and channel
print("3. Product × Channel cross statistics:")
cross_summary = sales.groupby(["Product", "Channel"])["Sales amount"].sum().unstack()
print(cross_summary)
print()
# 4. Calculate the proportion of sales for each product
print("4. Sales proportion:")
total = sales["Sales amount"].sum()
product_pct = sales.groupby("Product")["Sales amount"].sum() / total * 100
print(product_pct.round(2))
Other Extensionsgroupby is a core operation in data analysis; mastering it allows you to efficiently complete various statistical analysis tasks.