Pandas将列表值字典映射到DataFrame列并按元素数生成重复行
Pandas 字典映射按列表长度扩行方案
基础场景实现
目标:将值为列表的字典,按DataFrame指定列的键匹配映射为新列,按列表元素数量重复展开行,全程保持DataFrame格式。
首先修正示例输入的语法问题(字典键为字符串需加引号),定义测试数据:
import pandas as pd # 映射字典 d = {'a':['i','ii'], 'b':['iii','iv'], 'c':['v','vi','vii']} # 原始DataFrame df = pd.DataFrame({ 'Column1': ['g', 'h', 'i'], 'Column2': ['a', 'b', 'c'] })
实现代码:
# 匹配字典值生成新列,操作对象为DataFrame,不会转换为Series df['Column3'] = df['Column2'].map(d) # 按列表长度展开行,重置索引 df_result = df.explode('Column3', ignore_index=True)
执行后输出和预期完全一致:
Column1 Column2 Column3 0 g a i 1 g a ii 2 h b iii 3 h b iv 4 i c v 5 i c vi 6 i c vii
延伸问题1:叠加第二个字典二次映射扩行
首先修正示例d2的语法错误(分号改为逗号、字符串值加引号):
d2 = {'i':['A'],'ii':['B'],'iii':['C','D'],'iv':['E'],'v':['F'],'vi':['G'],'vii':['H','I','J']}
实现逻辑和单次映射完全一致,在上一步输出结果基础上重复映射+展开操作即可。如果需要保留原有第三列,就新增列存储二次映射结果;如果需要替换第三列,直接对第三列赋值映射结果即可。
示例代码(新增第四列存储二次映射结果):
df_result['Column4'] = df_result['Column3'].map(d2) df_result_2 = df_result.explode('Column4', ignore_index=True)
输出结果:
Column1 Column2 Column3 Column4 0 g a i A 1 g a ii B 2 h b iii C 3 h b iii D 4 h b iv E 5 i c v F 6 i c vi G 7 i c vii H 8 i c vii I 9 i c vii J
延伸问题2:映射源为DataFrame格式的实现
如果映射关系本身是DataFrame结构,有两种实现方式,输出结果和字典映射完全一致:
方法1:转换为字典后复用上述逻辑
适合小数据量场景,先把映射DataFrame转为{键:值列表}格式的字典,后续操作和基础场景完全相同:
# 示例映射源DataFrame:key_col存匹配键,val_col存对应列表值 map_df = pd.DataFrame({ 'key_col': ['a','b','c'], 'val_col': [['i','ii'], ['iii','iv'], ['v','vi','vii']] }) # 转为目标字典 map_dict = dict(zip(map_df['key_col'], map_df['val_col'])) # 后续复用基础场景代码 df['Column3'] = df['Column2'].map(map_dict) df_result = df.explode('Column3', ignore_index=True)
方法2:merge合并后直接展开
适合大数据量场景,无需手动转换字典,直接关联映射表后展开:
# 重命名映射表列名,和原表待匹配列、新生成列名对齐 map_df_renamed = map_df.rename(columns={'key_col':'Column2', 'val_col':'Column3'}) # 左连接关联后直接展开列表 df_result = df.merge(map_df_renamed, on='Column2', how='left').explode('Column3', ignore_index=True)
注意:如果待匹配列存在字典/映射表中不存在的键,映射结果会生成空值NaN,
explode会保留对应空行,可提前过滤映射键范围,或用fillna给空值赋值空列表避免异常。
内容的提问来源于stack exchange,提问作者Jnams
相关产品推荐
相关产品推荐

