Data AnalyticsPandas & NumPybeginner
Updated:

Pandas Pivot Tables for Analysis

4 min read

Pivot tables reshape data into cross-tabs the way spreadsheets do. Learn pivot_table with index, columns, values and aggfunc, plus totals and groupby differences.

TL;DR – Quick Answer

pd.pivot_table reshapes long data into a spreadsheet-style cross-tab: you choose a column for the rows (index), a column for the columns, a values column to aggregate, and an aggfunc such as mean or sum. It is the pandas version of an Excel pivot table and is ideal for two-dimensional summaries like sales by region and month. Add margins=True for row and column totals.

On This Page

If you have ever built a pivot table in a spreadsheet, dragging one field to rows, another to columns, and a number into the middle, pandas does the same thing in a single function call. pivot_table reshapes long, detailed data into a compact cross-tab that answers two-dimensional questions like "sales by region and by month" at a glance. It is one of the most stakeholder-friendly outputs an analyst can produce.

The power of a pivot is that it shows a metric broken down by two categories at once. Where groupby gives you a tall list, a pivot spreads a second dimension across the columns so the pattern jumps out visually.

The four ingredients of a pivot

Every pivot table is defined by four choices: which column becomes the rows (index), which becomes the columns (columns), which numeric column fills the cells (values), and how to combine values in each cell (aggfunc). Start with a small illustrative sample of sales data:

import pandas as pd

df = pd.DataFrame({
    "region": ["North", "North", "South", "South", "North", "South"],
    "month": ["Jan", "Feb", "Jan", "Feb", "Jan", "Jan"],
    "sales": [100, 120, 90, 110, 60, 40],
})

Now pivot region against month, summing sales:

table = pd.pivot_table(
    df,
    index="region",
    columns="month",
    values="sales",
    aggfunc="sum",
)
print(table)
month   Feb  Jan
region
North   120  160
South   110  130

In one call, the long six-row table became a clean region-by-month grid. North sold 160 in January (100 + 60) and 120 in February. This is exactly the layout stakeholders expect in a report.

Choosing the aggregation

The aggfunc controls what happens when multiple rows land in the same cell. The default is mean; common choices are sum, count, min and max:

avg_table = pd.pivot_table(df, index="region", columns="month",
                           values="sales", aggfunc="mean")
print(avg_table)
month    Feb   Jan
region
North  120.0  80.0
South  110.0  65.0

North's January cell is now 80, the average of 100 and 60, rather than their sum. Always be explicit about aggfunc so readers know whether a cell is a total or an average.

Adding totals with margins

Reports usually want row and column totals. margins=True adds an "All" row and column computed with the same aggregation:

print(pd.pivot_table(df, index="region", columns="month",
                     values="sales", aggfunc="sum", margins=True))
month   Feb  Jan  All
region
North   120  160  280
South   110  130  240
All     230  290  520

The grand total of 520 sits in the bottom-right corner, with subtotals along the edges. Rename the label with margins_name="Total" if you prefer.

Multiple aggregations and filling gaps

You can request several statistics at once by passing a list to aggfunc, and you can replace the NaN that appears when a combination has no data using fill_value:

pd.pivot_table(df, index="region", columns="month", values="sales",
               aggfunc="sum", fill_value=0)

fill_value=0 turns empty cells into zeros, which is usually what you want in a sales grid where a missing month simply means no sales.

pivot_table versus groupby

The two are close relatives. groupby(["region", "month"])["sales"].sum() computes the same numbers, but returns them as a tall Series with a MultiIndex. pivot_table takes that same result and unstacks the month level into columns, giving the two-dimensional layout. Choose groupby when you want a long, tidy result for further processing, and pivot_table when you want a wide, human-readable cross-tab for a report. For pure frequency counts of category combinations, pd.crosstab is an even shorter shortcut.

Practical usage

Pivot tables are the format stakeholders instinctively read: metric in the middle, two dimensions on the edges, totals in the corner. Analysts use them for revenue by product and region, headcount by department and level, conversion by channel and week. The typical flow is to prepare a clean long DataFrame, often after a merge and some filtering, then pivot it for presentation and export to Excel. Because it is code, the same pivot regenerates instantly when next month's data arrives, which is its advantage over building the same table by hand in a spreadsheet each time.

Common mistakes

  • Forgetting aggfunc and misreading cells. The default is mean, so if you expected sums your totals will look wrong. State the aggregation explicitly.
  • Duplicate combinations with the wrong tool. The plain df.pivot method errors when a row/column pair repeats. Use pivot_table, which aggregates duplicates, whenever combinations may not be unique.
  • Leaving NaN in a numeric report. Missing combinations produce NaN, which can break downstream math or look odd to readers. Use fill_value=0 when a blank truly means zero.
  • Pivoting on a high-cardinality column. Putting a column with hundreds of distinct values into columns creates an unwieldy, mostly empty grid. Keep the columns dimension small.

In interviews

Interviewers often ask you to produce a cross-tab, such as "show average order value by region and quarter," which is a direct pivot_table task. A common conceptual question is the difference between pivot_table and groupby, where the strong answer is that they compute the same aggregation but pivot_table reshapes one category into columns for a two-dimensional view. Being able to add margins for totals and explain aggfunc demonstrates you can turn raw data into a report a manager can actually read.

Where this fits in your learning path

Pivot tables build directly on groupby within the data analytics path, extending single-dimension summaries into two-dimensional cross-tabs. You will usually combine data with merge and join before pivoting, and you can prepare cell values with apply and map. Producing clean cross-tab reports is a highly visible part of the data analyst role.

Frequently Asked Questions

What is a pivot table in pandas?
A pivot table reshapes data so one categorical column becomes the rows, another becomes the columns, and a numeric column is aggregated into the cells. pd.pivot_table(df, index='region', columns='month', values='sales', aggfunc='sum') builds a region-by-month grid of total sales. It mirrors the pivot table feature in Excel.
What is the difference between pivot_table and groupby?
Both aggregate data by category, but groupby usually produces a long result with one row per group, while pivot_table spreads a second category across columns to make a two-dimensional grid. pivot_table also handles duplicate combinations by aggregating them, whereas the simpler pivot method does not. Use pivot_table when you want a cross-tab layout.
How do I add totals to a pandas pivot table?
Pass margins=True, which adds an 'All' row and column containing the totals, and margins_name to rename that label. The totals use the same aggfunc you specified. This is handy for reports where stakeholders expect row and column subtotals.
What does aggfunc do in pivot_table?
aggfunc sets the function used to combine values that fall into the same cell, such as 'mean', 'sum', 'count' or 'max'. The default is 'mean'. You can pass a list to compute several aggregations at once, or a dictionary to apply different functions to different value columns.
What is pandas crosstab used for?
pd.crosstab is a shortcut for building a frequency table or cross-tab from two or more columns, counting how often each combination occurs by default. It is essentially a specialized pivot_table focused on counts. Use it for quick counts of category combinations.

Want to Build Your Career in Data Analytics with AI?

Join CodeBegun and train with working industry engineers — See the Data Analytics course in Hyderabad

Apply for Demo Class →
Siva Prasad Galaba
Founder, CodeBegun · Staff Engineer

Founder of CodeBegun. 15+ years building Java systems at companies like Crunchyroll. Teaches Java, Spring Boot and system design the way the industry actually works, and mentors students through projects, mock interviews and placement preparation.

Technically reviewed by CodeBegun Technical TeamLast reviewed 16 July 2026 LinkedIn
Chat with us