一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

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 行数 ≈ 原始行数 × 列数,但远小于循环生成的临时对象开销。

该方案兼顾简洁性、可维护性与工业级性能,是处理此类“一主多从”宽表展开任务的标准实践。

热门栏目