数据重塑 #
数据重塑概述 #
数据重塑是改变数据形状和结构的操作,在数据清洗和分析中非常常用。
text
┌─────────────────────────────────────────────────────────────┐
│ 数据重塑方法 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 长格式 → 宽格式 │
│ ├── pivot() 透视 │
│ ├── pivot_table() 聚合透视 │
│ └── unstack() 展开多层索引 │
│ │
│ 宽格式 → 长格式 │
│ ├── melt() 熔化 │
│ └── stack() 堆叠 │
│ │
│ 其他操作 │
│ ├── transpose() 转置 │
│ └── T 转置属性 │
│ │
└─────────────────────────────────────────────────────────────┘
准备数据 #
python
import pandas as pd
import numpy as np
# 长格式数据
df_long = pd.DataFrame({
'date': ['2024-01-01', '2024-01-01', '2024-01-02', '2024-01-02'],
'city': ['Beijing', 'Shanghai', 'Beijing', 'Shanghai'],
'temperature': [5, 10, 6, 12],
'humidity': [30, 40, 35, 45]
})
print("长格式数据:")
print(df_long)
# 宽格式数据
df_wide = pd.DataFrame({
'date': ['2024-01-01', '2024-01-02', '2024-01-03'],
'Beijing_temp': [5, 6, 7],
'Shanghai_temp': [10, 12, 14],
'Beijing_humidity': [30, 35, 32],
'Shanghai_humidity': [40, 45, 42]
})
print("\n宽格式数据:")
print(df_wide)
pivot - 透视 #
pivot 将长格式数据转换为宽格式。
python
# 基本透视
result = df_long.pivot(index='date', columns='city', values='temperature')
print(result)
# city Beijing Shanghai
# date
# 2024-01-01 5 10
# 2024-01-02 6 12
# 多值透视
result = df_long.pivot(index='date', columns='city')
print(result)
# temperature humidity
# city Beijing Shanghai Beijing Shanghai
# date
# 2024-01-01 5 10 30 40
# 2024-01-02 6 12 35 45
# 透视后选择特定值
result = df_long.pivot(index='date', columns='city', values=['temperature', 'humidity'])
print(result['temperature'])
pivot 注意事项 #
python
# 如果有重复值,pivot 会报错
df_dup = pd.DataFrame({
'date': ['2024-01-01', '2024-01-01', '2024-01-01'],
'city': ['Beijing', 'Beijing', 'Shanghai'],
'temp': [5, 6, 10]
})
# 这会报错
# df_dup.pivot(index='date', columns='city', values='temp')
# ValueError: Index contains duplicate entries
# 使用 pivot_table 替代
result = df_dup.pivot_table(index='date', columns='city', values='temp', aggfunc='mean')
print(result)
pivot_table - 聚合透视 #
pivot_table 可以处理重复值,并支持聚合函数。
python
# 创建有重复值的数据
df = pd.DataFrame({
'date': ['2024-01-01', '2024-01-01', '2024-01-01', '2024-01-02', '2024-01-02'],
'city': ['Beijing', 'Beijing', 'Shanghai', 'Beijing', 'Shanghai'],
'temperature': [5, 7, 10, 6, 12]
})
# 使用均值聚合
result = df.pivot_table(index='date', columns='city', values='temperature', aggfunc='mean')
print(result)
# city Beijing Shanghai
# date
# 2024-01-01 6.0 10.0
# 2024-01-02 6.0 12.0
# 多种聚合函数
result = df.pivot_table(index='date', columns='city', values='temperature',
aggfunc=['mean', 'min', 'max', 'count'])
print(result)
# 多值聚合
result = df.pivot_table(index='date', columns='city',
values=['temperature', 'humidity'],
aggfunc='mean')
# 添加汇总
result = df.pivot_table(index='date', columns='city', values='temperature',
aggfunc='mean', margins=True)
# 填充缺失值
result = df.pivot_table(index='date', columns='city', values='temperature',
aggfunc='mean', fill_value=0)
melt - 熔化 #
melt 将宽格式数据转换为长格式。
python
# 基本熔化
result = df_wide.melt(id_vars='date')
print(result)
# date variable value
# 0 2024-01-01 Beijing_temp 5
# 1 2024-01-02 Beijing_temp 6
# 2 2024-01-03 Beijing_temp 7
# 3 2024-01-01 Shanghai_temp 10
# ...
# 指定值列
result = df_wide.melt(id_vars='date', value_vars=['Beijing_temp', 'Shanghai_temp'])
print(result)
# 自定义列名
result = df_wide.melt(id_vars='date',
var_name='city_metric',
value_name='value')
print(result)
# 分割变量名
result = df_wide.melt(id_vars='date')
result[['city', 'metric']] = result['variable'].str.split('_', expand=True)
print(result)
melt 实用技巧 #
python
# 部分列熔化
result = df_wide.melt(id_vars='date',
value_vars=['Beijing_temp', 'Shanghai_temp'],
var_name='city_temp',
value_name='temperature')
print(result)
# 保留特定列
result = df_wide.melt(id_vars=['date'],
value_vars=['Beijing_temp', 'Shanghai_humidity'])
print(result)
stack 和 unstack #
stack - 堆叠 #
stack 将列"堆叠"为行,使数据变长。
python
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
}, index=['x', 'y', 'z'])
# 堆叠
result = df.stack()
print(result)
# x A 1
# B 4
# C 7
# y A 2
# B 5
# C 8
# z A 3
# B 6
# C 7
# dtype: int64
# 堆叠多层索引 DataFrame
df_multi = pd.DataFrame(
np.random.randn(3, 4),
columns=pd.MultiIndex.from_product([['A', 'B'], ['x', 'y']])
)
result = df_multi.stack()
print(result)
unstack - 展开 #
unstack 将行"展开"为列,使数据变宽。
python
# 创建多层索引
index = pd.MultiIndex.from_product([['2024-01-01', '2024-01-02'],
['Beijing', 'Shanghai']])
df = pd.DataFrame({'temperature': [5, 10, 6, 12]}, index=index)
# 展开
result = df.unstack()
print(result)
# temperature
# city Beijing Shanghai
# date
# 2024-01-01 5 10
# 2024-01-02 6 12
# 展开指定层
result = df.unstack(level=0)
print(result)
# 填充缺失值
result = df.unstack(fill_value=0)
stack/unstack 配合使用 #
python
# stack 后 unstack 可以恢复
df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
stacked = df.stack()
unstacked = stacked.unstack()
print(unstacked.equals(df)) # True
transpose - 转置 #
python
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6]
})
# 转置
result = df.transpose()
print(result)
# 0 1 2
# A 1 2 3
# B 4 5 6
# 使用 T 属性
result = df.T
print(result)
实用案例 #
长宽格式转换 #
python
# 长格式 → 宽格式
df_long = pd.DataFrame({
'year': [2020, 2020, 2021, 2021],
'quarter': ['Q1', 'Q2', 'Q1', 'Q2'],
'sales': [100, 150, 120, 180]
})
df_wide = df_long.pivot(index='year', columns='quarter', values='sales')
print(df_wide)
# 宽格式 → 长格式
df_wide = pd.DataFrame({
'year': [2020, 2021],
'Q1': [100, 120],
'Q2': [150, 180]
})
df_long = df_wide.melt(id_vars='year', var_name='quarter', value_name='sales')
print(df_long)
多变量重塑 #
python
# 多变量数据
df = pd.DataFrame({
'date': ['2024-01-01', '2024-01-02'],
'Beijing_temp': [5, 6],
'Beijing_humidity': [30, 35],
'Shanghai_temp': [10, 12],
'Shanghai_humidity': [40, 45]
})
# 熔化并分割变量
result = df.melt(id_vars='date')
result[['city', 'metric']] = result['variable'].str.split('_', expand=True)
result = result.pivot_table(index=['date', 'city'], columns='metric', values='value').reset_index()
print(result)
时间序列重塑 #
python
# 时间序列数据
dates = pd.date_range('2024-01-01', periods=6, freq='D')
df = pd.DataFrame({
'date': dates,
'value': np.random.randn(6)
})
# 添加年月列
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
# 透视为月度表格
result = df.pivot_table(index='month', columns='day', values='value')
print(result)
重塑方法选择指南 #
text
┌─────────────────────────────────────────────────────────────┐
│ 重塑方法选择 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 场景 推荐方法 │
│ ──────────────────────── ──────────────────────────── │
│ 长格式 → 宽格式(无重复) df.pivot() │
│ 长格式 → 宽格式(有重复) df.pivot_table() │
│ 宽格式 → 长格式 df.melt() │
│ 多层索引展开 df.unstack() │
│ 列转行 df.stack() │
│ 行列互换 df.T 或 df.transpose() │
│ │
└─────────────────────────────────────────────────────────────┘
下一步 #
掌握了数据重塑后,接下来学习 时间序列,深入了解 Pandas 的时间序列处理功能!
最后更新:2026-04-04