You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效比较写法不一致的两列国家名称(Pandas/Spark方案均可)

Pandas 实现方案

方法1:标准化映射表(准确率优先)

先把各种不规范的国家名称统一映射到权威标准(比如ISO 3166官方名称),再做合并对比,适合长期维护:

  • 先构建映射字典(可以存成CSV批量导入,方便维护上百个国家):
    country_mapping = {
        "USA": "United States",
        "U.S.A.": "United States",
        "UK": "United Kingdom",
        "Britain": "United Kingdom",
        "China": "People's Republic of China",
        # 补充所有你遇到的变体
    }
    # 批量导入写法:
    # country_mapping = pd.read_csv("country_mappings.csv").set_index("variant")["standard"].to_dict()
    
  • 对两个DataFrame的country列做标准化:
    df_1["standard_country"] = df_1["country"].map(country_mapping).fillna(df_1["country"])
    df_2["standard_country"] = df_2["country"].map(country_mapping).fillna(df_2["country"])
    
  • 合并后对比标准化列:
    merged_df = pd.merge(df_1, df_2, on=["col_1", "col_2"], suffixes=("_1", "_2"))
    merged_df["country_match"] = merged_df["standard_country_1"] == merged_df["standard_country_2"]
    
  • 针对未覆盖的变体,用模糊匹配补全:
    先装依赖pip install fuzzywuzzy python-Levenshtein,再写函数匹配相似名称:
    from fuzzywuzzy import process
    
    standard_countries = list(country_mapping.values())
    def fuzzy_standardize(country):
        if country in standard_countries:
            return country
        match, score = process.extractOne(country, standard_countries)
        return match if score >= 80 else country  # 相似度阈值可调整
    
    df_1["standard_country"] = df_1["country"].apply(fuzzy_standardize)
    df_2["standard_country"] = df_2["country"].apply(fuzzy_standardize)
    

方法2:直接模糊匹配合并(快速验证)

不想维护映射表的话,直接在分组内做模糊匹配,适合临时需求:

from fuzzywuzzy import fuzz

# 按col_1、col_2分组,组内匹配相似国家名
def match_group(group):
    df1_rows = group[group["source"] == "df1"]
    df2_rows = group[group["source"] == "df2"]
    matches = []
    for _, r1 in df1_rows.iterrows():
        for _, r2 in df2_rows.iterrows():
            if fuzz.ratio(r1["country"], r2["country"]) >= 80:
                matches.append({**r1, **r2, "match_score": fuzz.ratio(r1["country"], r2["country"])})
    return pd.DataFrame(matches)

# 标记来源后分组匹配
df_1["source"] = "df1"
df_2["source"] = "df2"
combined = pd.concat([df_1, df_2])
result = combined.groupby(["col_1", "col_2"]).apply(match_group).reset_index(drop=True)
# 组内没匹配到的就是真正不匹配的记录
Spark 实现方案

方法1:广播映射表做标准化

把映射表广播到集群节点,避免重复传输:

import org.apache.spark.sql.functions._

// 构建映射字典
val countryMapping = Map(
  "USA" -> "United States",
  "UK" -> "United Kingdom",
  "Britain" -> "United Kingdom"
)
val broadcastMapping = spark.sparkContext.broadcast(countryMapping)

// 定义标准化UDF
val standardizeCountry = udf((country: String) => {
  broadcastMapping.value.getOrElse(country, country)
})

// 标准化后合并对比
val df1Standard = df_1.withColumn("standard_country", standardizeCountry(col("country")))
val df2Standard = df_2.withColumn("standard_country", standardizeCountry(col("country")))

val mergedDf = df1Standard.join(df2Standard, Seq("col_1", "col_2"), "inner")
  .withColumn("country_match", col("standard_country") === col("standard_country"))

方法2:内置编辑距离匹配

用Spark自带的levenshtein函数计算字符差异,设置阈值判断匹配:

// 合并后计算编辑距离,阈值根据需求调整
val mergedDf = df_1.join(df_2, Seq("col_1", "col_2"), "inner")
  .withColumn("edit_distance", levenshtein(col("country"), col("country")))
  .withColumn("country_match", col("edit_distance") <= 3)

内容的提问来源于stack exchange,提问作者johnnydoe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 06:05:29