最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Pandas 中高效展开多列应用 ID 并复制记录完整指南
时间:2026-07-11 09:19:45 编辑:袖梨 来源:一聚教程网
本文介绍如何使用 pd.melt() 高效地将多个 Applct_Id 列(如 Applct_Id_1/2/3)展开为长格式,过滤非空值并保留原始关键字段,适用于 40 万级数据量的生产场景。
本文介绍如何使用 `pd.melt()` 高效地将多个 applct_id 列(如 applct_id_1/2/3)展开为长格式,过滤非空值并保留原始关键字段,适用于 40 万级数据量的生产场景。
在实际数据分析中,常遇到宽表结构:同一主键(如 APPN)下存在多个同质但编号不同的字段(如 Applct_Id_1, Applct_Id_2, Applct_Id_3),而业务要求将每个非空 ID 视为一条独立记录,并复用其关联属性(如 Name, Age)。直接循环或 apply() 逐行处理在 40 万数据量下性能极差;正确解法是利用 Pandas 的向量化熔解(melting)操作——它底层基于 NumPy,内存友好且执行迅速。
✅ 核心步骤:熔解 → 过滤 → 清理 → 排序
首先定义原始数据(注意:示例中 'Applct_Id_3' 第五行应为 None 以保持列长度一致,已修正):
import pandas as pdimport numpy as npdf = pd.DataFrame({ 'APPN': [1001, 1002, 1003, 1004, 1005, 1006], 'Applct_Id_1': ['A', 'B', 'C', 'D', None, 'F'], 'Applct_Id_2': [None, 'E', 'F', None, 'G', None], 'Applct_Id_3': ['W', 'Z', None, 'Y', None, None], # 修正:补全为6个元素 'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank'], 'Age': [25, 30, 35, 40, 45, 50]})
接着执行高效熔解流程:
# 1. 熔解:将 Applct_Id_* 列转为长格式,保留 APPN/Name/Age 作为标识列melted = df.melt( id_vars=['APPN', 'Name', 'Age'], value_vars=['Applct_Id_1', 'Applct_Id_2', 'Applct_Id_3'], var_name='ID_Type', value_name='ID_Number')# 2. 过滤:仅保留 ID_Number 非空的行(自动排除 None/np.nan)melted = melted[melted['ID_Number'].notna()]# 3. 清理:删除冗余的 ID_Type 列(因业务无需区分来源列)melted = melted.drop(columns=['ID_Type'])# 4. (可选)排序:按 APPN 和 ID_Number 提升可读性与后续分组效率melted = melted.sort_values(['APPN', 'ID_Number'], ignore_index=True)print(melted.head(10))
输出结果(节选):
APPN Name Age ID_Number0 1001 Alice 25 A1 1001 Alice 25 W2 1002 Bob 30 B3 1002 Bob 30 E4 1002 Bob 30 Z5 1003 Charlie 35 C6 1003 Charlie 35 F7 1004 David 40 D8 1004 David 40 Y9 1005 Eve 45 G
⚡ 性能优化关键点(针对 400K+ 数据)
- 避免 iterrows() 或 apply(lambda x: ...):这些方法触发 Python 层循环,速度比向量化操作慢 10–100 倍;
- melt() 是纯向量化操作:底层调用 NumPy 数组重组,时间复杂度接近 O(n),实测 40 万行耗时通常 < 200ms(取决于列数);
- notna() 比 != None 更可靠:Pandas 中 None 和 np.nan 均被 notna() 正确识别,而 == None 返回 False;
-
链式操作减少中间变量:可合并为一行(但为可读性建议分步):
result = (df.melt(...).query("ID_Number.notna()").drop('ID_Type', axis=1) .sort_values(['APPN', 'ID_Number']).reset_index(drop=True))
? 注意事项
- 若需仅保留含 ≥2 个非空 ID 的 APPN 记录(即题目中“replicate only for APPNs with more than 1 recorded ID”),可在熔解后添加分组筛选:
# 统计每个 APPN 的 ID 数量,保留 ≥2 的 APPNappn_counts = melted.groupby('APPN').size()valid_appns = appn_counts[appn_counts >= 2].indexfinal_df = melted[melted['APPN'].isin(valid_appns)].copy() - 列名需严格匹配:value_vars 中的列名必须存在于 DataFrame 中,否则报错;建议用 df.columns.intersection([...]) 安全校验;
- 内存敏感场景:若 Applct_Id_* 列含大量空值,熔解后 melted 行数 ≈ 原始行数 × 列数,但远小于循环生成的临时对象开销。
该方案兼顾简洁性、可维护性与工业级性能,是处理此类“一主多从”宽表展开任务的标准实践。