Pivot Tables in Pandas – Powerful Data Reshaping with pivot_table() in Python 2026
The pivot_table() function is one of Pandas’ most powerful tools for data manipulation and reporting. It allows you to reshape data, create cross-tabulations, and generate summary tables similar to Excel pivot tables — but with much more flexibility and speed.
TL;DR — Key Parameters of pivot_table()
values– column(s) to aggregateindex– rows (grouping keys)columns– columns (grouping keys)aggfunc– aggregation function(s) to applymargins=True– add grand totals
1. Basic Pivot Table
import pandas as pd
# Create a small demo file so this example runs as-is
# (in your project, sales_data.csv is your real export)
import numpy as np
rng = np.random.default_rng(42)
n = 60
pd.DataFrame({
"order_date": pd.date_range("2025-10-01", periods=n, freq="3D"),
"customer_id": rng.integers(101, 121, n),
"customer_name": rng.choice([" ana", "ben ", "chen", "dana"], n),
"product_id": rng.integers(1, 9, n),
"region": rng.choice(["North", "South", "East", "West"], n),
"category": rng.choice(["Electronics", "Books", "Home"], n),
"payment_method": rng.choice(["card", "cash", "wallet"], n),
"segment": rng.choice(["consumer", "business"], n),
"quantity": rng.integers(1, 6, n),
"amount": rng.uniform(50, 2500, n).round(2),
}).assign(
ship_date=lambda d: d["order_date"] + pd.Timedelta(days=2),
status=lambda d: np.where(d["amount"] > 2000, "priority", "standard"),
).to_csv("sales_data.csv", index=False)
df = pd.read_csv("sales_data.csv", parse_dates=["order_date"])
# Helper columns: pivot_table() works best with real column names
df["month"] = df["order_date"].dt.to_period("M")
df["year"] = df["order_date"].dt.year
# Simple pivot table: Sales by Region and Category
pivot = pd.pivot_table(
df,
values="amount",
index="region",
columns="category",
aggfunc="sum",
margins=True, # add grand total
margins_name="Total"
).round(2)
print(pivot)
2. Advanced Pivot Table with Multiple Aggregations
report = pd.pivot_table(
df,
values=["amount", "quantity"],
index=["region", "month"],
columns="category",
aggfunc={
"amount": ["sum", "mean"],
"quantity": "sum"
},
# no margins here: margins=True fails with a dict of function lists in pandas 3.1
).round(2)
print(report)
3. Real-World Example: Sales Dashboard Style Pivot
dashboard = pd.pivot_table(
df,
values="amount",
index="region",
columns="year",
aggfunc=["sum", "mean", "count"],
margins=True
).round(2)
# Flatten multi-level columns
dashboard.columns = [f"{agg}_{year}" for agg, year in dashboard.columns]
print(dashboard)
4. Best Practices in 2026
- Use
pivot_table()instead of manualgroupby()+unstack()when you need a classic pivot layout - Specify
aggfuncas a dictionary when using multiple aggregation functions - Include
margins=Truefor quick grand totals - Combine with date components (year, month, quarter) extracted via
.dt - Use
fill_value=0to replace NaNs with zeros for cleaner reports
How pivot_table() Organises Data
A pivot table is a grouped summary arranged as a grid. The index argument decides the rows, columns decides the column headers, values chooses the numbers to summarise, and aggfunc chooses how they are combined. Under the hood pandas performs a groupby() on the row and column keys and then unstacks the column keys, so anything a pivot table shows can also be produced with grouping.
The default aggfunc is the mean, which surprises many people who expect a sum. Always set it explicitly so readers of your code know what the numbers mean.
Worked Example: Quarterly Sales Grid
This self-contained example builds a small sales table and pivots it into regions by quarter.
import pandas as pd
sales = pd.DataFrame({
"date": pd.to_datetime(["2026-01-15", "2026-02-20", "2026-04-03", "2026-05-12", "2026-04-28"]),
"region": ["North", "South", "North", "South", "South"],
"amount": [200, 150, 300, 100, 50],
})
sales["quarter"] = sales["date"].dt.quarter
grid = sales.pivot_table(index="region", columns="quarter", values="amount",
aggfunc="sum", fill_value=0, margins=True, margins_name="Total")
print(grid)
With a single aggregation function, margins=True works and adds a Total row and column. The North row shows 200 in quarter 1 and 300 in quarter 2, and the grand total is 800.
Common Mistakes
- Relying on the default mean: set
aggfuncevery time - Passing Series instead of column names: pandas 3 expects names for
indexandcolumns; add helper columns first - Combining
margins=Truewith a dict of function lists: this fails in pandas 3.1; add totals separately - Too many column keys: wide grids become unreadable; keep one or two
Quick Summary
index= rows,columns= headers,values+aggfunc= numbers- Set
aggfuncandfill_valueexplicitly - Use
marginsfor totals when using one function
Conclusion
Pivot tables in Pandas are incredibly powerful for reshaping and summarizing data. In 2026, mastering pd.pivot_table() allows you to create professional-looking cross-tabulations, dashboards, and management reports with just a few lines of code. It is often the fastest way to turn raw transactional data into actionable business insights.
Next steps:
- Take one of your datasets and create a pivot table using region/category/month as dimensions