
本文详解使用 pivot() 实现按指定列(如 order)将长格式 DataFrame 转换为宽格式的方法,支持多值列(quant/price)对齐、层级列重排序,并妥善处理不等长分组导致的缺失值。
本文详解使用 `pivot()` 实现按指定列(如 order)将长格式 dataframe 转换为宽格式的方法,支持多值列(quant/price)对齐、层级列重排序,并妥善处理不等长分组导致的缺失值。
在数据分析中,常需将“长格式”(long format)数据重塑为“宽格式”(wide format),尤其当同一主键(如 order)对应多条记录,且需横向展开多个指标(如 quant 和 price)时。Pandas 提供了强大而灵活的 DataFrame.pivot() 方法,专为此类结构化重塑设计。
以问题中的 Case 1 为例,原始 DataFrame 每个 order 出现两次,start-end 时间区间成对出现,目标是将 order 变为列头,同时保留 quant 和 price 作为子列。关键在于:
✅ 使用复合索引 ['start', 'end'] 作为行标识;
✅ 将 order 设为列变量(columns);
✅ 自动对多值列(quant, price)生成 MultiIndex 列;
✅ 后续通过 swaplevel() 和 sort_index() 规范列顺序,使 order 成为外层、指标为内层,提升可读性。
以下是完整可执行代码:
import pandas as pd
# 构造 Case 1 示例数据
df = pd.DataFrame({
'order': ['1', '1', '2', '2', '3', '3'],
'start': pd.to_datetime(['2023-04-01 04:00:00+0000', '2023-05-01 04:00:00+0000',
'2023-04-01 04:00:00+0000', '2023-05-01 04:00:00+0000',
'2023-04-01 04:00:00+0000', '2023-05-01 04:00:00+0000'], utc=True),
'end': pd.to_datetime(['2023-05-01 04:00:00+0000', '2023-06-01 04:00:00+0000',
'2023-05-01 04:00:00+0000', '2023-06-01 04:00:00+0000',
'2023-05-01 04:00:00+0000', '2023-06-01 04:00:00+0000'], utc=True),
'quant': [10, 10, 20, 30, 40, 50],
'price': [44, 44, 5, 6, 8, 8]
})
# 执行 pivot 转换
out = (df.pivot(index=['start', 'end'], columns='order')
.sort_index(axis=1, level=1, sort_remaining=False) # 按 order 数值顺序排序列
.swaplevel(axis=1) # 将 order 提升为外层列索引,quant/price 为内层
.sort_index(axis=1) # 最终按列名字典序整理(可选)
)
print(out)输出结果为标准宽格式 MultiIndex DataFrame:
order 1 2 3
quant price quant price quant price
start end
2023-04-01 04:00:00+00:00 2023-05-01 04:00:00+00:00 10 44 20 5 40 8
2023-05-01 04:00:00+00:00 2023-06-01 04:00:00+00:00 10 44 30 6 50 8对于 Case 2(order == '3' 出现 4 次,而其他 order 仅 2 次),pivot() 会自动用 NaN 填充缺失位置,无需额外干预——这正是其健壮性的体现。例如新增两行后,order 1 和 order 2 对应的第 3、4 组 quant/price 将自然显示为 NaN,完全符合预期。
⚠️ 注意事项:
- pivot() 要求 index + columns 的组合必须唯一,否则会报 ValueError: Index contains duplicate entries。若存在重复(如相同 start+end+order 多次出现),请先用 groupby().agg() 聚合(如取均值/首值)。
- 若需更复杂的聚合逻辑(如每个 order 内按时间排序后取 top-N),应改用 pivot_table() 并指定 aggfunc。
- 列层级顺序可通过 swaplevel() 和 reorder_levels() 精细控制;sort_index(axis=1) 可确保列名有序展示。
- 最终结果若需扁平化列名(如 '1_quant'),可用 out.columns = ['_'.join(map(str, col)) for col in out.columns]。
掌握 pivot() 不仅能高效完成长宽转换,更是构建透视分析、特征工程宽表的基础能力。建议结合 reset_index()、droplevel() 等方法进一步定制输出结构,适配下游建模或报表需求。










