如何在 Pandas 中安全地用代码映射更新县名(保留未匹配项原值)

6次阅读

如何在 Pandas 中安全地用代码映射更新县名(保留未匹配项原值)

本文介绍如何使用 `map()` 配合 `combine_first()` 在 pandas 中精准更新县名字段:仅对字典中定义的代码进行重命名(如添加省份后缀),其余行保持原始县名不变,避免意外引入 nan。

在处理波兰行政区划数据时,常遇到同名县(如多个“Powiat brzeski”)因所属省份不同而需唯一标识的问题。理想做法是基于唯一编码(Code)将县名扩展为“县名_省份”格式,但直接使用 df[‘County’] = df[‘Code’].map(code_to_county) 会导致未匹配代码对应行的 County 值变为 NaN——这正是原始问题的核心缺陷。

根本原因在于:Series.map() 对字典中不存在的键默认返回 NaN,而原始 County 列中这些行的有效值被完全覆盖。解决的关键是保留原始值作为兜底,而非全量替换。

✅ 推荐方案:combine_first()
该方法将映射结果(含部分 NaN)与原始列进行“优先级合并”:以左侧 Series 为基准,仅在其值为 NaN 的位置,用右侧 Series 的对应值填充。语义清晰、性能高效、无需循环或条件判断。

import pandas as pd  # 示例数据 data = {     'Code': [1202000, 2402000, 802000, 3017000, 3005000, 9999999],     'County': ['Powiat brzeski', 'Powiat bielski', 'Powiat krośnieński',                 'Powiat ostrowski', 'Powiat grodziski', 'Powiat ciechanowski'] } df = pd.DataFrame(data)  # 映射字典:仅包含需增强的县(带省份后缀) code_to_county = {     1202000: "Powiat brzeski_Malopolskie",     2402000: "Powiat bielski_Slaskie",     802000:  "Powiat krośnieński_Lubuskie",     3017000: "Powiat ostrowski_Wielkopolskie",     3005000: "Powiat grodziski_Wielkopolskie" }  # 安全更新:仅覆盖匹配项,其余保留原值 df['County'] = df['Code'].map(code_to_county).combine_first(df['County'])  print(df)

输出结果:

Code                          County 0  1202000      Powiat brzeski_Malopolskie 1  2402000          Powiat bielski_Slaskie 2   802000     Powiat krośnieński_Lubuskie 3  3017000  Powiat ostrowski_Wielkopolskie 4  3005000  Powiat grodziski_Wielkopolskie 5  9999999             Powiat ciechanowski

? 补充说明与最佳实践:

  • 为什么不用 fillna()? fillna() 虽可补 NaN,但若原始 County 列本身含 NaN,会错误覆盖;而 combine_first() 严格按索引对齐,更鲁棒。
  • 扩展性建议:若映射逻辑复杂(如需查表、正则匹配),可改用 merge() 左连接替代 map(),同样配合 combine_first() 或 fillna() 处理缺失。
  • 验证步骤:更新后建议执行 df[df[‘Code’].isin(code_to_county.keys())][‘County’].str.contains(‘_’) 快速校验增强是否生效。

此方法兼顾准确性与健壮性,是处理“选择性字段增强”场景的标准范式。

text=ZqhQzanResources