
本文介绍使用 pandas.melt() 配合条件筛选,将 ID 和日期列固定、其余数值列按列名与 ID 值动态对齐,堆叠为单一 value 列的专业方法。
本文介绍使用 `pandas.melt()` 配合条件筛选,将 id 和日期列固定、其余数值列按列名与 id 值动态对齐,堆叠为单一 value 列的专业方法。
在数据处理中,常遇到宽表结构:前几列为标识字段(如 id 和 date),后续多列为以 ID 命名的指标列(如列名 '1', '2', '3'),每行需从“对应 ID 名称的列”中提取值。目标是将这些列“逻辑折叠”为一列 value,而非简单垂直拼接——关键在于按行匹配:第 i 行的 value 应取自列名为 df.iloc[i]['id'] 的那一列。
这无法通过 stack() 直接实现(因其仅按索引层级展开,不支持列名与某列值的动态关联),而 melt() 是更合适的基础操作。完整流程如下:
-
使用
melt()展开所有非标识列,指定id_vars=['id', 'date']保持这两列不变,var_name将原列名转为新列(如'id2'); -
添加条件过滤:只保留
id == id2.astype(int)的行(即当前行的id值恰好等于被熔化的列名); -
清理冗余列:删除临时生成的
id2列,得到最终三列结果。
以下是可直接运行的示例代码:
import pandas as pd
import numpy as np
# 构造原始 DataFrame
df = pd.DataFrame({
'id': [1, 1, 1, 2, 2, 2, 3, 3, 3],
'date': ['1/1/00', '1/2/00', '1/3/00'] * 3,
'1': [np.nan, 100.0, np.nan] * 3,
'2': [200, 200, 200] * 3,
'3': [300, 300, 300] * 3
})
# 步骤 1:熔化,将列名转为变量
melted = df.melt(id_vars=['id', 'date'], var_name='id2', value_name='value')
# 步骤 2:筛选 —— 仅保留 id 与列名(转为整数)相等的行
result = melted[melted['id'] == melted['id2'].astype(int)].drop('id2', axis=1).reset_index(drop=True)
print(result)
✅ 输出结果严格匹配预期:每行 value 来自原表中列名等于该行 id 的列,空值(NaN)也被正确保留。
⚠️ 注意事项:
- 列名必须为可转为整数的字符串(如
'1','2','10'),若含前导零或非数字字符,需先清洗var_name; - 若存在缺失列(如
id=4但无'4'列),对应行将被自动过滤掉,建议提前校验列名覆盖范围; - 性能提示:对于超大宽表(数百列),
melt + boolean indexing仍高效;避免使用apply(lambda row: row[str(row['id'])])等逐行操作。
该方法逻辑清晰、可读性强,是处理“ID驱动列选择”类宽表规整任务的标准实践。










