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

DataFrame字符串精准匹配标准化及非指定列保留技术问询

DataFrame国家名称标准化匹配问题及原列保留需求

核心问题

  • 现有正则匹配逻辑无法实现完整字符串精准匹配,会错误匹配包含目标子串的内容(比如把Example1 and中的Example1误匹配)
  • 希望最终输出的DataFrame自动保留原数据中所有非指定列(如year),无需手动指定列名

原实现代码

import re
from functools import reduce
import pandas as pd

def match_country_codes(df, country_codes):
    # Create a regex pattern to match whole words
    pattern = '|'.join(rf'\b{re.escape(c)}\b' for c in country_codes[['country', 'alpha1', 'alpha2']].values.flatten())
    # new column for matches between pattern and df['country'] items
    df['matched_country'] = df['country'].str.extract(f'({pattern})', flags=re.IGNORECASE)
    # Merge with 'country_codes' dataframe to get the full country names
    # merge over 3 frames for all columns
    df1 = df.merge(country_codes, left_on='matched_country', right_on='country', how='left')
    df2 = df.merge(country_codes, left_on='matched_country', right_on='alpha1', how='left')
    df3 = df.merge(country_codes, left_on='matched_country', right_on='alpha2', how='left')

    dataframes = [df1, df2, df3]
    # merge all dataframes together on '[['country_y']]'
    result = reduce(lambda x, y: x.merge(y, on=['country_y'], how='left'), dataframes)
    # Drop rows with None or NaN values in the 'country_y' column
    result = result.dropna(subset=['country_y'])
    # return result
    return result

示例数据

df = pd.DataFrame({'country': ['foobar', 'foo and bar', 'Example1 and', 'PQR'], 
                  'year':[2018, 2019, 'NA',2017] 
                      })
country_codes = pd.DataFrame({'country': ['FooBar', 'Example1', 'foo and bar and foo', 'Example'],
                   'alpha1': ['foobar', 'Bosnia', 'ABC', 'DEF'],
                   'alpha2': ['GHI', 'JKL', 'MNO', 'PQR']             
                             })

当前问题表现

运行match_country_codes(df, country_codes)会错误匹配到Example1,且原列保留逻辑混乱,出现大量冗余列。

期望输出

仅匹配完全一致的内容(忽略大小写),同时自动保留原所有列:

data = {'country': ['foobar', 'PQR'],
        'year': [2018, 2017],
        'standard_country': ['FooBar', 'Example']
           }

desired_output = pd.DataFrame(data, index=[0, 3])

解决方案

关键优化点

  1. 精准完全匹配:构建大小写不敏感的映射字典,将所有可能的匹配值(country、alpha1、alpha2)映射到标准国家名称,避免子串误匹配
  2. 自动保留原列:直接在原DataFrame基础上添加标准化列,避免多次合并导致的列冗余

修改后的代码

import pandas as pd

def match_country_codes(df, country_codes):
    # 构建大小写不敏感的匹配映射:所有可能的输入值 -> 标准国家名
    match_map = {}
    for _, row in country_codes.iterrows():
        standard_name = row['country']
        # 把country、alpha1、alpha2都加入映射,统一转小写作为键
        for col in ['country', 'alpha1', 'alpha2']:
            match_key = str(row[col]).lower()
            match_map[match_key] = standard_name
    
    # 对原df的country列做匹配,生成标准化列
    df['standard_country'] = df['country'].str.lower().map(match_map)
    
    # 过滤掉匹配失败的行,保留所有原列
    result = df.dropna(subset=['standard_country']).copy()
    
    return result

测试验证

运行以下代码:

result = match_country_codes(df, country_codes)
print(result)

输出结果:

country  year standard_country
0  foobar  2018           FooBar
3     PQR  2017           Example

完全符合期望,自动保留了year列,且无错误匹配情况。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:35:07