Data Analysis Advanced: Joins, Reshaping and Time Series
Reshaping with Pivot and Melt
In this lesson you will
- Explain long and wide data
- Build a summary table with pivot_table
- Convert wide data to long with melt
Introduction
The same facts can be laid out in different shapes. Some questions are easy in one shape and awkward in another. Knowing how to convert between them is a core data skill.
Long and wide
Long data has one row per observation, with columns saying what each is:
| month | region | revenue |
|---|---|---|
| Jan | N | 100 |
| Jan | S | 80 |
| Feb | N | 120 |
| Feb | S | 90 |
Wide data spreads values across columns:
| month | N | S |
|---|---|---|
| Jan | 100 | 80 |
| Feb | 120 | 90 |
Wide tables are easy for people to read, such as reports and spreadsheets. Long tables are usually best for grouping, filtering and plotting with code, because every variable has its own column.
pivot_table: long to wide, with summaries
Python
import pandas as pd
sales = pd.DataFrame({
"month": ["Jan", "Jan", "Feb", "Feb"],
"region": ["N", "S", "N", "S"],
"revenue": [100, 80, 120, 90],
})
print(sales.pivot_table(index="month", columns="region",
values="revenue", aggfunc="sum"))region N S
month
Feb 120 90
Jan 100 80Notice that the months came out in alphabetical order, with Feb before Jan. pandas sorted the text labels. For real analyses, store months as real dates or ordered categories so the order is correct (the next lesson shows how).
pivot_table handles duplicates by aggregating them. If two rows had the same month and region, aggfunc="sum" would add them. Other choices include "mean", "count" and "max". Add margins=True to include totals, and fill_value=0 to replace gaps.
Quick quiz
What does aggfunc do in pivot_table?
melt: wide to long
Python
wide = pd.DataFrame({
"product": ["A", "B"],
"Jan": [10, 20],
"Feb": [15, 25],
})
print(wide.melt(id_vars="product", var_name="month", value_name="units")) product month units
0 A Jan 10
1 B Jan 20
2 A Feb 15
3 B Feb 25id_varsare the columns to keep as they are.- The other columns are "melted" into two: one holding the old column names (
var_name) and one holding the values (value_name).
Once in long form, you can group by month or product easily, or pass it to plotting tools that expect one row per data point.
Related tools
df.pivot(...)reshapes without aggregating, and fails if there are duplicates.df.stack()anddf.unstack()move index levels between rows and columns.pd.crosstab(a, b)counts how often combinations of two categories occur.groupby(...).agg(...)is often simpler than a pivot when you just want summary numbers.
Choosing the shape
- Decide what you want to do with the table.
- For analysis and plotting by code, aim for long data.
- For a final report or spreadsheet for people, make a wide pivot at the end.
- Keep your raw data untouched, and do the reshaping in code so it is repeatable.
Try it yourself
Take a table of exam scores with one column per subject. Melt it to long form, then pivot it back to wide with the average score per class and subject.
Summary
- Long data has one row per observation, and wide data spreads values across columns.
pivot_tableturns long into wide and aggregates duplicates, andmeltdoes the reverse.- Text labels sort alphabetically, so use real dates or ordered categories for correct ordering.
Lesson complete
+20 XP
Nice work. Keep going while it is fresh.
Sources and further reading