Pandas如何通过手机号前缀子串匹配对比两个DataFrame纠正国家名称
手机号最长前缀匹配国家名高效实现方案
核心匹配规则:优先取csv_df中长度最长的、可作为small_df前缀开头的映射记录,获取对应正确国家名。
前置预处理
首先统一两个表的前缀格式,避免数值类型匹配误差:
import pandas as pd # 把两个表的prefix统一转为字符串格式 csv_df['prefix_str'] = csv_df['prefix'].astype(str) small_df['prefix_str'] = small_df['prefix'].astype(str)
方案1:排序优先匹配法(适用于csv_df前缀量小于1万的场景)
将csv_df按前缀长度降序排序,匹配时第一个命中的就是最长前缀,逻辑简单易实现:
# csv_df按前缀长度降序排序,保证长前缀优先匹配 csv_df_sorted = csv_df.sort_values(by='prefix_str', key=lambda x: x.str.len(), ascending=False) # 匹配函数:找第一个符合startswith规则的国家名 def match_country(target_prefix): for p, c in zip(csv_df_sorted['prefix_str'], csv_df_sorted['country']): if target_prefix.startswith(p): return c # 无匹配时可自定义返回值,比如返回原错误国家名 return None # 生成正确国家名列替换原列 small_df['country'] = small_df['prefix_str'].apply(match_country) # 清理辅助列 small_df = small_df.drop(columns='prefix_str')
方案2:前缀树(Trie)匹配法(适用于csv_df前缀量大于1万的大数据场景)
前缀树查询时间仅和手机号长度相关,性能远高于遍历匹配:
# 前缀树节点定义 class TrieNode: __slots__ = ('children', 'country') def __init__(self): self.children = {} self.country = None # 1. 构建前缀树 root = TrieNode() for prefix, country in zip(csv_df['prefix_str'], csv_df['country']): node = root for digit in prefix: if digit not in node.children: node.children[digit] = TrieNode() node = node.children[digit] # 前缀结束节点存储对应国家名 node.country = country # 2. 前缀查询函数:返回最长匹配的国家名 def query_longest_prefix(target_prefix): node = root latest_country = None for digit in target_prefix: if digit not in node.children: break node = node.children[digit] if node.country is not None: latest_country = node.country return latest_country # 3. 批量匹配替换 small_df['country'] = small_df['prefix_str'].apply(query_longest_prefix) # 清理辅助列 small_df = small_df.drop(columns='prefix_str')
两种方案都可以直接得到你给出的预期输出结果,可根据自己的数据规模选择。
内容的提问来源于stack exchange,提问作者Sinceris
相关产品推荐
相关产品推荐

