使用difflib匹配DataFrame中CallType列未获预期结果的问题
呼叫类型映射问题及解决方案
问题描述
原始DataFrame数据:
CallType 0 IN 1 OUT 2 a_in 3 asms 4 INCOMING 5 OUTGOING 6 A2P_SMSIN 7 ain 8 aout
期望映射结果:
CallType 0 IN 1 OUT 2 IN 3 SMS 4 IN 5 OUT 6 SMS 7 IN 8 OUT
尝试使用difflib.get_close_matches实现,但仅匹配到IN和OUT,其余结果为空列表:
import pandas as pd import difflib CALL_TYPE=['IN','OUT','SMS','VOICE','SMT'] def test1(): final_file_data = pd.DataFrame({ 'CallType': ['IN', 'OUT', 'a_in', 'asms', 'INCOMING', 'OUTGOING','A2P_SMSIN', 'ain', 'aout']}) print(final_file_data) final_file_data['CallType'] = final_file_data['CallType'].apply(lambda x: difflib.get_close_matches(x, CALL_TYPE, n=1))
实际输出:
CallType 0 [IN] 1 [OUT] 2 [] 3 [] 4 [] 5 [] 6 [] 7 [] 8 []
问题原因
difflib.get_close_matches默认使用字符串整体相似度(基于编辑距离的ratio值),阈值为0.6。而你的数据中,a_in、INCOMING这类字符串和目标关键词(如IN)的整体相似度远低于0.6,因此无法匹配。例如INCOMING和IN的相似度仅约0.33,达不到阈值要求。
解决方案
方法一:基于关键词包含的自定义映射
通过判断目标关键词是否存在于原字符串中(忽略大小写),实现精准映射:
import pandas as pd CALL_TYPE = ['IN', 'OUT', 'SMS', 'VOICE', 'SMT'] def map_call_type(x): x_lower = x.lower() for typ in CALL_TYPE: if typ.lower() in x_lower: return typ return x # 无匹配时返回原值 def test1(): final_file_data = pd.DataFrame({ 'CallType': ['IN', 'OUT', 'a_in', 'asms', 'INCOMING', 'OUTGOING','A2P_SMSIN', 'ain', 'aout'] }) print("原始数据:") print(final_file_data) final_file_data['CallType'] = final_file_data['CallType'].apply(map_call_type) print("\n映射后结果:") print(final_file_data) test1()
方法二:正则表达式匹配
构建正则模式,优先匹配长关键词(避免短关键词误匹配),实现映射:
import pandas as pd import re CALL_TYPE = ['IN', 'OUT', 'SMS', 'VOICE', 'SMT'] # 按关键词长度从长到短排序,避免短关键词优先匹配 pattern = re.compile('|'.join(sorted(CALL_TYPE, key=len, reverse=True)), flags=re.IGNORECASE) def map_call_type(x): match = pattern.search(x) return match.group().upper() if match else x def test1(): final_file_data = pd.DataFrame({ 'CallType': ['IN', 'OUT', 'a_in', 'asms', 'INCOMING', 'OUTGOING','A2P_SMSIN', 'ain', 'aout'] }) print("原始数据:") print(final_file_data) final_file_data['CallType'] = final_file_data['CallType'].apply(map_call_type) print("\n映射后结果:") print(final_file_data)
(不推荐)调低difflib阈值
如果一定要使用difflib,可以调低匹配阈值,但可能出现错误匹配:
final_file_data['CallType'] = final_file_data['CallType'].apply( lambda x: difflib.get_close_matches(x, CALL_TYPE, n=1, cutoff=0.3)[0] if difflib.get_close_matches(x, CALL_TYPE, n=1, cutoff=0.3) else x )
该方法可能导致asms匹配到SMT而非SMS,因此不建议使用。
内容的提问来源于stack exchange,提问作者arpit joshi
相关产品推荐
相关产品推荐

