Pandas Data Reshaping (pivot / melt / stack / unstack)
Data reshaping is a common operation in data analysis, used to change the layout structure of data. Pandas provides functions such as pivot, melt, stack, and unstack to convert between long format and wide format.
pivot Pivot Table
pivotConverts long format data to wide format, similar to Excel's pivot table feature.
Basic Usage
Example
import pandas as pd
# Create long format data
df = pd.DataFrame({
"Date": ["2024-01-01", "2024-01-01", "2024-01-02", "2024-01-02"],
"Product": ["A", "B", "A", "B"],
"Sales": [100, 150, 120, 90]
})
print("Long format data:")
print(df)
print()
# Convert to wide format
pivot_df = df.pivot(index="Date", columns="Product", values="Sales")
print("Wide format data:")
print(pivot_df)
# Create long format data
df = pd.DataFrame({
"Date": ["2024-01-01", "2024-01-01", "2024-01-02", "2024-01-02"],
"Product": ["A", "B", "A", "B"],
"Sales": [100, 150, 120, 90]
})
print("Long format data:")
print(df)
print()
# Convert to wide format
pivot_df = df.pivot(index="Date", columns="Product", values="Sales")
print("Wide format data:")
print(pivot_df)
Multiple Index
Example
import pandas as pd
df = pd.DataFrame({
"Year": ["2024", "2024", "2024", "2024"],
"Quarter": ["Q1", "Q1", "Q2", "Q2"],
"Product": ["A", "B", "A", "B"],
"Sales": [100, 150, 120, 90]
})
print("Data:")
print(df)
print()
# Multiple index pivot
pivot_df = df.pivot(index=["Year", "Quarter"], columns="Product", values="Sales")
print("Multiple index pivot:")
print(pivot_df)
df = pd.DataFrame({
"Year": ["2024", "2024", "2024", "2024"],
"Quarter": ["Q1", "Q1", "Q2", "Q2"],
"Product": ["A", "B", "A", "B"],
"Sales": [100, 150, 120, 90]
})
print("Data:")
print(df)
print()
# Multiple index pivot
pivot_df = df.pivot(index=["Year", "Quarter"], columns="Product", values="Sales")
print("Multiple index pivot:")
print(pivot_df)
Aggregate Function
Example
import pandas as pd
# Case with duplicate values
df = pd.DataFrame({
"Date": ["2024-01-01", "2024-01-01", "2024-01-01", "2024-01-02"],
"Product": ["A", "A", "B", "B"],
"Sales": [100, 110, 80, 90]
})
print("Data with duplicate values:")
print(df)
print()
# pivot does not support duplicate values by default, you need to use pivot_table and specify an aggregate function
pivot_df = df.pivot_table(index="Date", columns="Product", values="Sales", aggfunc="sum")
print("Aggregating with sum:")
print(pivot_df)
print()
# Use mean
print("Aggregating with mean:")
print(df.pivot_table(index="Date", columns="Product", values="Sales", aggfunc="mean"))
# Case with duplicate values
df = pd.DataFrame({
"Date": ["2024-01-01", "2024-01-01", "2024-01-01", "2024-01-02"],
"Product": ["A", "A", "B", "B"],
"Sales": [100, 110, 80, 90]
})
print("Data with duplicate values:")
print(df)
print()
# pivot does not support duplicate values by default, you need to use pivot_table and specify an aggregate function
pivot_df = df.pivot_table(index="Date", columns="Product", values="Sales", aggfunc="sum")
print("Aggregating with sum:")
print(pivot_df)
print()
# Use mean
print("Aggregating with mean:")
print(df.pivot_table(index="Date", columns="Product", values="Sales", aggfunc="mean"))
pivotDuplicate values are not allowed; when there are duplicate values, usepivot_tableand specify an aggregate function.
melt Unpivot
meltConverts wide format data to long format, the reverse operation of pivot.
Example
import pandas as pd
# Create wide format data
df = pd.DataFrame({
"Date": ["2024-01-01", "2024-01-02"],
"A": [100, 120],
"B": [150, 90]
})
print("Wide format data:")
print(df)
print()
# Convert to long format
melted = df.melt(id_vars="Date", var_name="Product", value_name="Sales")
print("Long format data:")
print(melted)
# Create wide format data
df = pd.DataFrame({
"Date": ["2024-01-01", "2024-01-02"],
"A": [100, 120],
"B": [150, 90]
})
print("Wide format data:")
print(df)
print()
# Convert to long format
melted = df.melt(id_vars="Date", var_name="Product", value_name="Sales")
print("Long format data:")
print(melted)
Keep Multiple Columns Unchanged
Example
import pandas as pd
df = pd.DataFrame({
"City": ["Beijing", "Shanghai"],
"2023 Revenue": [1000, 800],
"2023 Profit": [200, 150],
"2024 Revenue": [1200, 950],
"2024 Profit": [250, 180]
})
print("Wide format:")
print(df)
print()
# Keep "City" unchanged, convert other columns to long format
melted = df.melt(
id_vars="City",
var_name="Indicator",
value_name="Value"
)
print("Long format:")
print(melted)
df = pd.DataFrame({
"City": ["Beijing", "Shanghai"],
"2023 Revenue": [1000, 800],
"2023 Profit": [200, 150],
"2024 Revenue": [1200, 950],
"2024 Profit": [250, 180]
})
print("Wide format:")
print(df)
print()
# Keep "City" unchanged, convert other columns to long format
melted = df.melt(
id_vars="City",
var_name="Indicator",
value_name="Value"
)
print("Long format:")
print(melted)
stack and unstack
stack and unstack are reshaping functions dedicated to MultiIndex.
unstack
Example
import pandas as pd
# Create data with multiple index levels
df = pd.DataFrame({
"A": [1, 2, 3, 4],
"B": [5, 6, 7, 8]
}, index=pd.MultiIndex.from_tuples(
[("X", 1), ("X", 2), ("Y", 1), ("Y", 2)],
names=["Category", "Number"]
))
print("Multi-level index data:")
print(df)
print()
# unstack converts inner index to columns
print("After unstack:")
print(df.unstack())
# Create data with multiple index levels
df = pd.DataFrame({
"A": [1, 2, 3, 4],
"B": [5, 6, 7, 8]
}, index=pd.MultiIndex.from_tuples(
[("X", 1), ("X", 2), ("Y", 1), ("Y", 2)],
names=["Category", "Number"]
))
print("Multi-level index data:")
print(df)
print()
# unstack converts inner index to columns
print("After unstack:")
print(df.unstack())
stack
Example
import pandas as pd
# Create wide format (with column index)
df = pd.DataFrame({
("A", "X"): [1, 2],
("A", "Y"): [3, 4],
("B", "X"): [5, 6],
("B", "Y"): [7, 8]
})
print("With multi-level column index:")
print(df)
print()
# stack converts column index to inner index
print("After stack:")
print(df.stack())
# Create wide format (with column index)
df = pd.DataFrame({
("A", "X"): [1, 2],
("A", "Y"): [3, 4],
("B", "X"): [5, 6],
("B", "Y"): [7, 8]
})
print("With multi-level column index:")
print(df)
print()
# stack converts column index to inner index
print("After stack:")
print(df.stack())
Practice: Business Report Conversion
Example
import pandas as pd
# Simulate business data - sales records
sales = pd.DataFrame({
"Date": ["2024-01"] * 4,
"Product": ["Phone", "Computer", "Tablet", "Headphones"],
"Channel": ["Online", "Online", "Offline", "Online"],
"Sales Amount": [10000, 20000, 8000, 5000]
})
print("Raw sales data:")
print(sales)
print()
# Convert using pivot
pivot = sales.pivot_table(
index="Product",
columns="Channel",
values="Sales Amount",
aggfunc="sum",
fill_value=0
)
print("Channel sales pivot:")
print(pivot)
print()
# Restore to long format
print("Restored to long format:")
print(pivot.reset_index().melt(id_vars="Product", var_name="Channel", value_name="Sales Amount"))
# Simulate business data - sales records
sales = pd.DataFrame({
"Date": ["2024-01"] * 4,
"Product": ["Phone", "Computer", "Tablet", "Headphones"],
"Channel": ["Online", "Online", "Offline", "Online"],
"Sales Amount": [10000, 20000, 8000, 5000]
})
print("Raw sales data:")
print(sales)
print()
# Convert using pivot
pivot = sales.pivot_table(
index="Product",
columns="Channel",
values="Sales Amount",
aggfunc="sum",
fill_value=0
)
print("Channel sales pivot:")
print(pivot)
print()
# Restore to long format
print("Restored to long format:")
print(pivot.reset_index().melt(id_vars="Product", var_name="Channel", value_name="Sales Amount"))
Reshaping Function Selection
| Function | Purpose | Typical Scenario |
|---|---|---|
pivot |
Long → Wide | Row-column conversion |
pivot_table |
Long → Wide (with aggregation) | When there are duplicate values |
melt |
Wide → Long | Data tidying |
unstack |
Index → Column | Multi-level index |
stack |
Column → Index | Multi-level index |
Other ExtensionsThe purpose of data reshaping is to make data more suitable for analysis or presentation. Choose the appropriate conversion method based on downstream requirements.