
本文介绍如何使用 pandas 的 melt、stack 或 explode 等方法,将 dataframe 中特定列(如 aka、lqaka)的非空值“下移”为独立行,并将其对应类型(aka/lqaka)赋给 name type 列,同时保留原始主行及其他辅助列的结构完整性。
本文介绍如何使用 pandas 的 melt、stack 或 explode 等方法,将 dataframe 中特定列(如 aka、lqaka)的非空值“下移”为独立行,并将其对应类型(aka/lqaka)赋给 name type 列,同时保留原始主行及其他辅助列的结构完整性。
在数据清洗与标准化场景中,常需将宽表中多个别名类字段(如 AKA、LQAKA)展开为长格式——即每个非空别名独占一行,并继承原始记录的关键标识(如 Name Type),同时将原字段名转化为新的类型标签。本教程提供三种稳健、可扩展的实现方案。
✅ 推荐方案:melt + dropna + 重映射
这是最清晰、易调试的方法,适用于含任意数量固定列(如 Other, Other2 等)的通用场景:
import pandas as pd
data = {
'Name Type': ["Primary", "Primary", "Primary"],
'Full Name': ["John Snow", "Daenerys Targaryen", "Brienne Tarth"],
'AKA': ["Aegon Targaryen", None, None],
'LQAKA': ["The Bastard of Winterfell", "Mother of Dragons", None],
'Other': ["Info", "Info", "Info"]
}
df = pd.DataFrame(data)
# 步骤1:保留关键列(Name Type, Other),其余列熔化为长格式
cols_to_keep = ['Name Type', 'Other']
out = (df.melt(cols_to_keep, ignore_index=False)
.dropna(subset='value') # 自动过滤 None/NaN
.sort_index(kind='stable', ignore_index=True)
.rename(columns={'value': 'Full Name'}))
# 步骤2:识别非 Full Name 行,用 variable 列填充 Name Type,并清空其他辅助列
m = out['variable'] != 'Full Name'
out.loc[m, 'Name Type'] = out.pop('variable')
out.loc[m, cols_to_keep[1:]] = '' # 清空除 Name Type 外的保留列(如 Other)
# 步骤3:确保列序一致(Name Type, Full Name, 其他保留列)
result = out[['Name Type', 'Full Name'] + cols_to_keep[1:]].reset_index(drop=True)
print(result)
输出:
Name Type Full Name Other 0 Primary John Snow Info 1 AKA Aegon Targaryen 2 LQAKA The Bastard of Winterfell 3 Primary Daenerys Targaryen Info 4 LQAKA Mother of Dragons 5 Primary Brienne Tarth Info
⚡ 简洁替代:stack 一步到位
若仅需处理 Full Name、AKA、LQAKA 三列,且辅助列固定为 Name Type 和 Other,stack 更简洁高效:
out = df.set_index(['Name Type', 'Other']).stack().reset_index(name='Full Name')
m = out['level_2'] != 'Full Name'
out.loc[m, 'Name Type'] = out.pop('level_2')
out.loc[m, 'Other'] = ''
result = out[['Name Type', 'Full Name', 'Other']].reset_index(drop=True)
? 注意:stack() 会自动忽略 NaN,无需显式 dropna;但要求索引列无重复或缺失,否则需提前校验。
? 扩展支持:列表型字段(如 AKA 为字符串列表)
当 AKA 或 LQAKA 列含列表(如 ["Aegon Targaryen", "Lord Snow"])时,需追加 .explode():
# 假设 AKA/LQAKA 可能为 list 或 scalar
out = (df.melt(cols_to_keep, ignore_index=False)
.dropna(subset='value')
.sort_index(kind='stable', ignore_index=True)
.rename(columns={'value': 'Full Name'})
.explode('Full Name', ignore_index=True)) # 展开列表项为多行
m = out['variable'] != 'Full Name'
out.loc[m, 'Name Type'] = out.pop('variable')
out.loc[m, cols_to_keep[1:]] = ''
result = out[['Name Type', 'Full Name'] + cols_to_keep[1:]].reset_index(drop=True)
? 关键注意事项
- 列名敏感性:melt 中 id_vars 必须明确指定需保留的“主键列”,避免误熔化;
- 空值处理:dropna(subset='value') 是安全底线,但若存在空字符串 '' 需额外 .replace('', pd.NA).dropna(...);
- 顺序保证:sort_index(kind='stable') 确保原始行序不因熔化打乱;
- 性能提示:对超大表(百万级),优先用 stack(底层优化);需灵活列选择时用 melt 更可控。
该模式广泛适用于人员别名、产品多规格、地址多类型等“一主多辅”结构的规范化转换,是 pandas 数据重塑的经典实践。











