基于Metaphone编码与Levenshtein距离匹配DataFrame地名
基于Metaphone编码与Levenshtein距离的地名匹配实现方案
背景说明
- df1:包含3万条文本语句,已通过以下代码生成
metaphone编码列:
编码示例:df1['metaphone'] = df1['text'].apply(lambda x:' '.join([jellyfish.metaphone(i) for i in x.split()]))M HLT WL STRT NKST JN I WL TRFL T S0 AFRK AFTR 0T WL S M MM IN JRTN 0N I RTRN BK ENKLNT,最终列包含text、metaphone、matched code、country。 - df2:包含480条国家/城市名称,同样生成了
metaphone编码列。
需求
仅通过metaphone编码列,利用Levenshtein距离匹配df1语句中的地名与df2地名,在df1中生成matched code(匹配到的编码列表)和country(对应真实地名列表),示例输出:
| matched code | country |
|---|---|
| [S0 AFRK, JRTN, ENKLNT] | [South Africa, Jordan, England] |
实现步骤
1. 预处理df2编码映射
先构建df2中编码到真实地名的映射,同时记录地名编码的词数(优先匹配多词地名,避免短编码误匹配):
import pandas as pd from Levenshtein import distance # 假设df2包含'name'(真实地名)和'metaphone'列 df2['code_words'] = df2['metaphone'].str.split() df2['word_count'] = df2['code_words'].apply(len) # 构建编码到地名的字典 code_to_country = dict(zip(df2['metaphone'], df2['name'])) # 获取df2中所有不同的地名词数,按降序排列 sorted_word_counts = sorted(df2['word_count'].unique(), reverse=True)
2. 定义匹配函数
对df1的每条编码语句,按词数从多到少滑动窗口匹配,通过Levenshtein距离阈值筛选有效匹配:
def match_place_codes(metaphone_str, code_map, word_counts, max_distance=1): sentence_codes = metaphone_str.split() matched_codes = [] matched_countries = [] i = 0 while i <= len(sentence_codes) - 1: hit = False # 优先尝试匹配多词地名 for wc in [cnt for cnt in word_counts if cnt <= len(sentence_codes)-i]: window_code = ' '.join(sentence_codes[i:i+wc]) # 遍历df2编码计算距离 for code, country in code_map.items(): if distance(window_code, code) <= max_distance: matched_codes.append(code) matched_countries.append(country) i += wc hit = True break if hit: break if not hit: i += 1 return matched_codes, matched_countries
3. 批量应用匹配到df1
# 对df1每条数据执行匹配,生成目标列 df1[['matched code', 'country']] = df1['metaphone'].apply( lambda x: pd.Series(match_place_codes(x, code_to_country, sorted_word_counts)) )
4. 优化方向
- 阈值调整:
max_distance可根据实际匹配精度调整,多词地名可适当提高阈值 - 效率优化:3万条数据可通过预编码索引、批量计算距离等方式提升速度
- 去重处理:若同一编码多次匹配,可添加
list(set())类逻辑去重
内容的提问来源于stack exchange,提问作者Iqbal Baki
相关产品推荐
相关产品推荐

