pandas字符串匹配新增列 实现城市与国家映射分类
代码逻辑问题排查
原代码存在4处核心逻辑错误,导致输出不符合预期:
- 作用域错误:在
apply调用的行处理函数中直接修改DataFrame整列,而非操作当前遍历的单行数据,只要任意一行匹配到美国城市,整列US都会被赋值为1 - 循环终止逻辑错误:遍历单个国家的城市列表时,只要第一个城市未匹配就直接
return None终止所有循环,既不会检查同国家的其他城市,也不会遍历后续其他国家的映射规则 - 列初始化缺失:没有提前为所有国家代码创建默认值为0的列,最终只生成了最先匹配到的
US列,缺失CA、UK列 - 返回值逻辑混乱:函数没有返回当前行对应各个国家的匹配结果,完全依赖全局变量修改,不符合
apply方法的使用逻辑
正确实现方案
基础易懂版(逐行匹配,逻辑清晰)
先对映射字典做小写预处理避免重复转换,初始化所有国家列默认值为0,再逐行匹配赋值:
import pandas as pd # 构造示例数据 df = pd.DataFrame({ 'City': ['I lived Los Angeles', 'I visited London and Toronto','the best one is Toronto', 'business hub is in New York',' Mexico city is stunning'] }) # 国家-城市映射关系 country_map = { 'US': ['New York','Los Angeles','San Diego'], 'CA': ['Montreal','Toronto','Manitoba'], 'UK': ['London','Liverpool','Manchester'] } # 预处理:所有城市名统一转小写,匹配时不区分大小写 country_map_lower = {k: [city.lower() for city in v] for k, v in country_map.items()} # 初始化所有国家列,默认值0,整数类型 for code in country_map.keys(): df[code] = 0 # 逐行匹配 for idx, row in df.iterrows(): text = row['City'].lower() for code, cities in country_map_lower.items(): for city in cities: if city in text: df.at[idx, code] = 1 break # 匹配到当前国家的任意城市即停止遍历该国家剩余城市
高性能版(向量化操作,适合大数据量场景)
不用逐行循环,用pandas内置字符串匹配方法,运行效率提升10倍以上:
# 统一转小写做匹配 text_series = df['City'].str.lower() for code, cities in country_map_lower.items(): # 拼接正则匹配规则,匹配任意一个城市即标记为1 pattern = '|'.join(cities) df[code] = text_series.str.contains(pattern, regex=True).astype(int)
运行后输出结果完全符合预期:
City US CA UK 0 I lived Los Angeles 1 0 0 1 I visited London and Toronto 0 1 1 2 the best one is Toronto 0 1 0 3 business hub is in New York 1 0 0 4 Mexico city is stunning 0 0 0
注意:当前子串匹配规则如果需要避免误匹配(比如避免把"New Yorks"误识别为"New York"),可以给正则加上单词边界
\b,把pattern改为'|'.join([rf'\b{city}\b' for city in cities])即可。
内容的提问来源于stack exchange,提问作者MTALY
相关产品推荐
相关产品推荐

