
本文介绍使用 pandas 的 melt、stack 和 explode 等方法,将 aka、lqaka 等辅助名称列中非空值“下移”为独立行,同时将原行保留为 primary 类型,并动态设置 name type 字段为对应列名(如 aka/lqaka),其他列(如 other)仅在 primary 行保留值。
本文介绍使用 pandas 的 melt、stack 和 explode 等方法,将 aka、lqaka 等辅助名称列中非空值“下移”为独立行,同时将原行保留为 primary 类型,并动态设置 name type 字段为对应列名(如 aka/lqaka),其他列(如 other)仅在 primary 行保留值。
在数据清洗与标准化场景中,常需将宽表中多个“别名类”列(如 AKA、LQAKA)展开为长格式——即每个非空别名生成一条新记录,紧随其所属的主记录(Primary)之后,且新记录的 Name Type 自动设为对应列名,而其他辅助列(如 Other)仅保留在主行中,别名行留空。这种结构对后续分组、排序或导入下游系统(如 CRM 或图谱数据库)至关重要。
以下提供三种稳健、可扩展的实现方案,均基于 pandas 1.5+,兼顾简洁性与泛化能力。
✅ 方案一:melt + dropna + 后处理(推荐,逻辑清晰)
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)为标识,熔化其余列
out = (df.melt(['Name Type', 'Other'], ignore_index=False)
.dropna(subset='value') # 移除 value 为 None 的行
.sort_index(kind='stable', ignore_index=True) # 按原始顺序稳定排序
.rename(columns={'value': 'Full Name'}) # 统一名称字段
)
# 步骤2:识别非 Full Name 行(即来自 AKA/LQAKA 的行),重赋 Name Type 并清空 Other
mask = out['variable'] != 'Full Name'
out.loc[mask, 'Name Type'] = out.pop('variable') # 将列名转为 Name Type
out.loc[mask, 'Other'] = '' # 清空辅助列
print(out)输出:
Name Type Other Full Name 0 Primary Info John Snow 1 AKA Aegon Targaryen 2 LQAKA The Bastard of Winterfell 3 Primary Info Daenerys Targaryen 4 LQAKA Mother of Dragons 5 Primary Info Brienne Tarth
✅ 优势:语义明确,易于调试;支持任意数量的“别名列”,只需调整 melt 的 id_vars 参数。
✅ 方案二:stack(更简洁,自动跳过 NaN)
out = (df.set_index(['Name Type', 'Other'])
.stack() # 自动忽略 NaN,返回 MultiIndex Series
.reset_index(name='Full Name')
.rename(columns={'level_2': 'Name Type'})
)
# 将原 Full Name 行的 Name Type 保持为 Primary,其余设为列名
mask = out['Name Type'] != 'Full Name'
out.loc[mask, 'Other'] = ''
# 注意:此处需手动恢复 Primary 行的 Name Type(因 stack 会覆盖)
out.loc[~mask, 'Name Type'] = 'Primary'
# 重排列顺序确保一致性
out = out[['Name Type', 'Full Name', 'Other']]该方式代码更短,但需额外处理 Name Type 的原始值还原,适合列结构固定且无嵌套需求的场景。
⚠️ 扩展:处理多列与嵌套列表(如 AKA 为 list)
若 AKA 或 LQAKA 列含列表(如 ["Aegon Targaryen", "Lord Snow"]),需增加 .explode():
# 假设 AKA/LQAKA 可能为 list 或 scalar
cols_to_melt = df.columns.difference(['Full Name']) # 动态识别所有非 Full Name 列
out = (df.melt(['Name Type', 'Other'], ignore_index=False)
.dropna(subset='value')
.sort_index(kind='stable', ignore_index=True)
.rename(columns={'value': 'Full Name'})
.explode('Full Name', ignore_index=True) # 展开列表项为多行
)
mask = out['variable'] != 'Full Name'
out.loc[mask, 'Name Type'] = out.pop('variable')
out.loc[mask, ['Other']] = ''
out = out[['Name Type', 'Full Name', 'Other']]? 关键注意事项
- 索引稳定性:sort_index(kind='stable') 确保原始行序不被破坏,避免 Primary 与别名错位;
- 列名保留:id_vars 中应包含所有需在 Primary 行完整保留的列(如 Other, Other2 等),其余列为待熔化列;
- 空值处理:dropna(subset='value') 是安全前提,务必确认 None/np.nan 已统一;
- 性能提示:对百万级数据,优先用 stack(底层 C 优化);需调试时选 melt 更直观。
最终结果严格满足需求:每条 Primary 记录后紧跟其非空别名行,Name Type 准确映射来源列,辅助列仅 Primary 行填充,结构规整、语义清晰,可直接用于报表或 ETL 流程。

















