Pandas DataFrame合并难题:字符串显示相同但Unicode编码不同
解决pd.merge中Unicode编码差异导致的字符串不匹配问题
pd.merge本身无法直接忽略Unicode编码差异,但可以通过标准化/清理字符串的方式,让显示相同的字符变成完全一致的可匹配格式,以下是几种实用解决方案:
1. Unicode标准化(处理等价字符)
很多看似相同的字符是Unicode等价形式(比如带重音的字符有组合字符、预组合字符两种编码),用unicodedata.normalize统一成标准格式即可:
import unicodedata import pandas as pd def normalize_str(s): # NFC格式会把组合字符合并为单个预组合字符,是最常用的标准化规则 return unicodedata.normalize('NFC', s) # 对两个数据集的匹配列做标准化 for col in ['state', 'county']: data1[col] = data1[col].apply(normalize_str) data2[col] = data2[col].apply(normalize_str) # 执行合并 merged_data = pd.merge(data1, data2, on=['state', 'county'])
2. 清理不可见/格式差异字符
如果字符串里藏着不可见控制字符、全角/半角空格差异,用正则和字符转换统一清理:
import re import pandas as pd def clean_str(s): # 移除所有不可见控制字符 s = re.sub(r'[\x00-\x1F\x7F-\x9F]', '', s) # 统一空格:去首尾空格、合并连续空格、全角空格转半角 s = ' '.join(s.strip().split()).replace(' ', ' ') # 全角字母/数字转半角 def full2half(c): code = ord(c) if 0xFF01 <= code <= 0xFF5E: return chr(code - 0xFEE0) return c return ''.join([full2half(c) for c in s]) # 应用到匹配列 for col in ['state', 'county']: data1[col] = data1[col].apply(clean_str) data2[col] = data2[col].apply(clean_str)
3. 定位编码差异(排查问题)
如果不确定具体差异类型,可以输出字符串的Unicode编码点,精准定位问题:
# 注意pandas是0索引,第308行对应索引307 print([ord(c) for c in data1.loc[307, 'county']]) # 第20691行对应索引20690 print([ord(c) for c in data2.loc[20690, 'county']])
对比两组编码点,就能明确是存在额外字符,还是字符编码本身不同,再针对性处理。
4. 模糊匹配(极端场景)
如果以上方法都无效,可以用模糊匹配做近似匹配(需安装fuzzywuzzy库):
from fuzzywuzzy import process import pandas as pd # 为data2创建合并键 data2['match_key'] = data2['state'] + '_' + data2['county'] def find_match(row): target_key = row['state'] + '_' + row['county'] # 匹配相似度≥90的结果(阈值可调整) best_match = process.extractOne(target_key, data2['match_key'], score_cutoff=90) return best_match[0] if best_match else None # 为data1添加匹配键 data1['matched_key'] = data1.apply(find_match, axis=1) # 基于匹配键合并 merged_data = pd.merge(data1, data2, left_on='matched_key', right_on='match_key')
注意:模糊匹配可能出现错误匹配,合并后需要验证结果准确性。
内容的提问来源于stack exchange,提问作者user496181
相关产品推荐
相关产品推荐

