基于旧Pandas DataFrame创建新DataFrame的优化方案问询
Pandas 长表转宽表优化方案
问题场景
现有数据库生成的长格式Pandas DataFrame(df_2)结构如下:
| obj_id | Column B | Column C |
|---|---|---|
| 1 | weight | 150 |
| 1 | height | 5.8 |
| 1 | eye_color | blue |
| 2 | weight | 160 |
需要将其转换为宽格式DataFrame,提取指定标签(如weight)作为独立列,最终期望的新DataFrame(df)结构如下:
| obj_id | weight |
|---|---|
| 1 | 150 |
| 2 | 160 |
| 3 | 140 |
| 4 | 150 |
后续还需处理5-10个类似标签(如height、eye_color等),当前已有可行但效率低下的实现方式,寻求更优方案。
现有低效实现
当前通过apply结合逐行遍历的方式实现,代码如下:
import pandas as pd # old dataframe = df_2 # new dataframe = df def myfunction(row): new_id = row['obj_id'] for index, rows in df_2.iterrows(): if new_id == rows['obj_id']: if "weight" in rows['Column B']: return rows['Column C'] df['weight'] = df.apply(myfunction, axis=1)
该实现存在明显缺陷:
- 依赖
iterrows()逐行遍历,大数据量下效率极低 - 为每个标签重复编写相似逻辑,代码冗余度高
优化方案:使用Pandas内置重塑函数
Pandas提供的pivot或pivot_table函数专门用于长表转宽表场景,能高效完成需求且代码简洁。
方法1:pivot(无重复记录场景)
如果每个obj_id+Column B的组合唯一(无重复值),直接使用pivot:
import pandas as pd # 生成包含所有标签的宽表 wide_df = df_2.pivot(index='obj_id', columns='Column B', values='Column C').reset_index() # 筛选需要的列(如仅保留weight) target_df = wide_df[['obj_id', 'weight']] # 与已有包含全量obj_id的df合并(补全3、4这类缺失的id) df = target_df.merge(your_existing_df[['obj_id']], on='obj_id', how='right')
方法2:pivot_table(存在重复记录场景)
如果同一obj_id+Column B存在多条记录,需要聚合处理(如取第一个值、均值),使用pivot_table:
wide_df = df_2.pivot_table( index='obj_id', columns='Column B', values='Column C', aggfunc='first' # 可替换为mean、sum等聚合逻辑 ).reset_index() # 筛选指定列 target_df = wide_df[['obj_id', 'weight']] # 合并到全量obj_id的df df = target_df.merge(your_existing_df[['obj_id']], on='obj_id', how='right')
多标签批量处理
若需提取多个标签(如weight、height、eye_color),只需修改列名列表即可,无需重复编写逻辑:
target_columns = ['weight', 'height', 'eye_color'] df = wide_df[['obj_id'] + target_columns].merge(your_existing_df[['obj_id']], on='obj_id', how='right')
方案优势
- 效率提升显著:基于Pandas向量化操作,比逐行遍历快数十倍
- 代码简洁:一行完成长转宽,无需自定义循环函数
- 扩展性强:新增标签仅需修改列名列表,核心逻辑无需改动
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

