
本文介绍如何基于原始长格式 dataframe(含 obj_id、属性名、属性值三列),快速筛选并透视指定属性(如 weight、height 等),生成结构清晰的宽格式新 dataframe,避免低效循环,提升代码可读性与执行性能。
在实际数据分析中,尤其是从关系型数据库导出的数据,常以“长格式”(long format)存储:每行仅记录一个对象(obj_id)的一项属性(如 Column B 为属性名,Column C 为对应值)。但后续建模或可视化往往需要“宽格式”(wide format)——即每个属性独占一列,每行代表一个对象的完整快照。例如,将 obj_id, Column B, Column C 的三列结构,转换为 obj_id, weight, height, eye_color 等多列结构。
直接使用 df.apply() + 内层 iterrows()(如原问题中的 myfunction)不仅语法冗长、逻辑易错,更因 Python 层面循环严重拖慢性能,尤其在处理数万行以上数据时尤为明显。Pandas 提供了专为该场景设计的高效向量化方案:条件过滤 + pivot。
✅ 推荐做法:先过滤再透视(推荐)
假设原始 DataFrame 名为 df,结构如下:
import pandas as pd
df = pd.DataFrame({
'obj_id': [1, 1, 1, 2, 2, 3, 4],
'Column B': ['weight', 'height', 'eye_color', 'weight', 'height', 'weight', 'weight'],
'Column C': [150, 5.8, 'blue', 160, 6.1, 140, 150]
})要提取 weight 属性并构建新 DataFrame,只需一行链式操作:
out = (df.query('`Column B` == "weight"')
.pivot(index='obj_id', columns='Column B', values='Column C')
.reset_index()
.rename_axis(columns=None))输出结果为:
obj_id weight 0 1 150 1 2 160 2 3 140 3 4 150
? 注意:列名 Column B 含空格,需用反引号 `Column B` 包裹,否则 query() 会报错。
? 扩展支持多个属性(如 weight + height + eye_color)
若需同时提取多个属性列,只需扩展过滤条件,并利用 pivot 的天然能力一次性完成宽表构建:
# 指定需保留的属性列表
keep_attrs = ['weight', 'height', 'eye_color']
out = (df.loc[df['Column B'].isin(keep_attrs)]
.pivot(index='obj_id', columns='Column B', values='Column C')
.reset_index()
.rename_axis(columns=None))该方法自动对 obj_id 去重(若某 obj_id 缺失某属性,则对应单元格为 NaN),结果列顺序与 keep_attrs 中顺序一致(Pandas 2.0+ 支持 sort=False 进一步确保顺序)。
⚠️ 注意事项与最佳实践
- 避免先 pivot 后筛选:如 df.pivot(...)[['weight']],会在内存中先生成包含所有属性(可能上百列)的宽表,再丢弃不需要的列,造成显著内存浪费和性能下降。
- 处理缺失值:若某些 obj_id 缺少指定属性,pivot 默认填充 NaN;如需填充默认值(如 0 或 'N/A'),可在 pivot 后接 .fillna(0)。
- 数据类型统一:pivot 后各列类型由原始 Column C 决定。若需强制转换(如 weight 列转为整型),可添加 .astype({'weight': 'int'}) —— 注意需确保无 NaN,否则需先 .fillna() 或用 Int64(支持空值的整型)。
- 去重保障:确保 (obj_id, Column B) 组合唯一。若存在重复(如同一 obj_id 有两条 weight 记录),pivot 将报错 ValueError: Index contains duplicate entries。此时应先用 drop_duplicates(subset=['obj_id', 'Column B'], keep='last') 显式去重。
✅ 总结
用 query() 或 loc 先精准筛选目标属性行,再通过 pivot() 一次性完成索引重塑与列展开,是构建宽格式 DataFrame 的标准、高效、可维护方案。它完全规避了 Python 循环,充分利用 Pandas 底层优化,代码简洁且语义清晰。对于 5–10 个常用属性的提取任务,此模式可轻松扩展,是生产环境中的首选实践。









