Python遍历DataFrame匹配元组列表生成region_code列的问题
问题与解决方案
现有数据
DataFrame df示例:
name1 name2 region_name 0 Salo saloo UPPER SINDAN 1 rnelih NaN RIMAN TRIST 2 benini NaN Lower Tangi ... ... ... ... 999 kremith kremithin MIKLAR 1000 Riro rirron LOWER BASTI
数据库获取的元组列表ls示例:
[(47, 'Upper Sindan', ''), (48, 'Riman Tah', 'Riman Trist'), (27, 'Timbari', 'Timbarlin'), (768, 'MIKLAR', ''), (769, 'Dindan', ''), (770, 'Shina Hardi',''), (..., '.........','...'), (921, 'KIMAN DARIB', 'lower basti')]
需求
遍历df,将region_name列的每个值与ls中元组的第2、3个元素做大小写不敏感匹配:
- 匹配成功:将对应元组的第一个数值填入新列
region_code - 匹配失败:填空值
- 若所有行都无匹配:不创建
region_code列
失败代码问题分析
第一段代码
for item in ls: if df['region_name'].str.contains(item[1]).any() or df['region_name'].str.contains(item[2]).any(): df['region_code']=item[0] else: df['region_code']=""
问题:
- 每次循环都会给整列
region_code赋值,最终只会保留最后一个item的判断结果 str.contains默认大小写敏感,且空字符串''会匹配所有文本,逻辑完全混乱- 未针对每行单独匹配,而是判断整列是否存在匹配
第二段代码
for index, row1 in df.iterrows(): for item in ls: if (row1[2] == item[1]) or (row1[2] == item[2]): df["region_code"] = item[0] else: df["region_code"] = ""
问题:
- 同样每次循环给整列赋值,最后覆盖为最后一个
item的结果 - 直接用
==做精确匹配,未处理大小写差异,导致大小写不同的内容无法匹配 - 未处理
region_name为空的情况(如果存在)
第三段代码
for index, row1 in df.iterrows(): for item in ls: if (row1[2].str.lower() == item[1].str.lower()) or (row1[2].str.lower() == item[1].str.lower()): df["region_code"] = item [0] else: df["region_code"] = ""
问题:
row1[2]是单个字符串(不是pandas Series),不能使用.str.lower(),直接用.lower()即可- 依然存在整列赋值覆盖的问题
最优实现方案
利用pandas矢量化操作+映射字典,避免低效循环,同时解决大小写匹配问题:
# 构建大小写不敏感的映射字典:键为小写的区域名,值为对应的code region_map = {} for code, name1, name2 in ls: # 仅处理非空的区域名 if name1.strip(): region_map[name1.lower()] = code if name2.strip(): region_map[name2.lower()] = code # 生成region_code列:转小写后匹配字典,空值填充为'' df['region_code'] = df['region_name'].str.lower().map(region_map).fillna('') # 如果所有行都无匹配,删除该列 if df['region_code'].eq('').all(): df.drop('region_code', axis=1, inplace=True)
说明
- 映射字典提前整理所有可匹配的区域名(转小写),确保大小写不敏感匹配
- 用
str.lower()统一转换为小写后匹配,避免大小写差异问题 - 过滤空字符串,防止空值误匹配所有内容
- 最后判断列是否全为空,符合“完全无匹配则不创建列”的需求
- 若存在多个相同的区域名(不同大小写),字典中后加入的会覆盖先加入的,可根据需求调整
name1和name2的加入顺序
内容的提问来源于stack exchange,提问作者Hoss
相关产品推荐
相关产品推荐

