现在位置: 首页 > Pandas 教程 > 正文

Pandas 数据重塑(pivot / melt / stack / unstack)

数据重塑是数据分析中的常见操作,用于改变数据的布局结构。Pandas 提供了 pivot、melt、stack、unstack 等函数来实现长格式和宽格式之间的转换。


pivot 透视表

pivot 将长格式数据转换为宽格式,类似于 Excel 的透视表功能。

基本用法

实例

import pandas as pd

# 创建长格式数据
df = pd.DataFrame({
    "日期": ["2024-01-01", "2024-01-01", "2024-01-02", "2024-01-02"],
    "产品": ["A", "B", "A", "B"],
    "销量": [100, 150, 120, 90]
})

print("长格式数据:")
print(df)
print()

# 转换为宽格式
pivot_df = df.pivot(index="日期", columns="产品", values="销量")
print("宽格式数据:")
print(pivot_df)

多重索引

实例

import pandas as pd

df = pd.DataFrame({
    "年份": ["2024", "2024", "2024", "2024"],
    "季度": ["Q1", "Q1", "Q2", "Q2"],
    "产品": ["A", "B", "A", "B"],
    "销量": [100, 150, 120, 90]
})

print("数据:")
print(df)
print()

# 多重索引透视
pivot_df = df.pivot(index=["年份", "季度"], columns="产品", values="销量")
print("多重索引透视:")
print(pivot_df)

聚合函数

实例

import pandas as pd

# 有重复值的情况
df = pd.DataFrame({
    "日期": ["2024-01-01", "2024-01-01", "2024-01-01", "2024-01-02"],
    "产品": ["A", "A", "B", "B"],
    "销量": [100, 110, 80, 90]
})

print("有重复值的数据:")
print(df)
print()

# pivot 默认不支持重复值,需要用 pivot_table 并指定聚合函数
pivot_df = df.pivot_table(index="日期", columns="产品", values="销量", aggfunc="sum")
print("使用 sum 聚合:")
print(pivot_df)
print()

# 使用 mean
print("使用 mean 聚合:")
print(df.pivot_table(index="日期", columns="产品", values="销量", aggfunc="mean"))

pivot 不允许有重复值,有重复值时使用 pivot_table 并指定聚合函数。


melt 逆透视

melt 将宽格式数据转换为长格式,是 pivot 的逆操作。

实例

import pandas as pd

# 创建宽格式数据
df = pd.DataFrame({
    "日期": ["2024-01-01", "2024-01-02"],
    "A": [100, 120],
    "B": [150, 90]
})

print("宽格式数据:")
print(df)
print()

# 转换为长格式
melted = df.melt(id_vars="日期", var_name="产品", value_name="销量")
print("长格式数据:")
print(melted)

保持多列不变

实例

import pandas as pd

df = pd.DataFrame({
    "城市": ["北京", "上海"],
    "2023营收": [1000, 800],
    "2023利润": [200, 150],
    "2024营收": [1200, 950],
    "2024利润": [250, 180]
})

print("宽格式:")
print(df)
print()

# 保持"城市"不变,其他列转换为长格式
melted = df.melt(
    id_vars="城市",
    var_name="指标",
    value_name="数值"
)
print("长格式:")
print(melted)

stack 与 unstack

stack 和 unstack 是 MultiIndex 专用的重塑函数。

unstack

实例

import pandas as pd

# 创建带多层索引的数据
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=["类别", "编号"]
))

print("多层索引数据:")
print(df)
print()

# unstack 将内层索引转为列
print("unstack 后:")
print(df.unstack())

stack

实例

import pandas as pd

# 创建宽格式(带列索引)
df = pd.DataFrame({
    ("A", "X"): [1, 2],
    ("A", "Y"): [3, 4],
    ("B", "X"): [5, 6],
    ("B", "Y"): [7, 8]
})

print("带多层列索引:")
print(df)
print()

# stack 将列索引转为内层索引
print("stack 后:")
print(df.stack())

实战:业务报表转换

实例

import pandas as pd

# 模拟业务数据 - 销售记录
sales = pd.DataFrame({
    "日期": ["2024-01"] * 4,
    "产品": ["手机", "电脑", "平板", "耳机"],
    "渠道": ["线上", "线上", "线下", "线上"],
    "销售额": [10000, 20000, 8000, 5000]
})

print("原始销售数据:")
print(sales)
print()

# 使用 pivot 转换
pivot = sales.pivot_table(
    index="产品",
    columns="渠道",
    values="销售额",
    aggfunc="sum",
    fill_value=0
)
print("渠道销售透视:")
print(pivot)
print()

# 还原为长格式
print("还原为长格式:")
print(pivot.reset_index().melt(id_vars="产品", var_name="渠道", value_name="销售额"))

重塑函数选择

函数 作用 典型场景
pivot 长→宽 行列转换
pivot_table 长→宽(带聚合) 有重复值时
melt 宽→长 数据整理
unstack 索引→列 多层索引
stack 列→索引 多层索引

数据重塑的目的是为了让数据更适合分析或展示。根据下游需求选择合适的转换方式。