如何批量获取Pandas DataFrame各列匹配指定模式值的行索引
问题说明
- 测试数据构造代码如下:
import pandas as pd task1 = pd.DataFrame({'task1': ['|ReviewNG-Cecum Landmark','|ReviewNG-Cecum Landmark','|Cecum Landmark','|Cecum Landmark','|Cecum Landmark','|Cecum Landmark','|ReviewNG-Cecum Landmark', '|ReviewNG-Cecum Landmark','|Other','|Other','|Other']}) task2 = pd.DataFrame({'task2': ['|Cecum Landmark|Other','|Cecum Landmark|Other','|Cecum Landmark|Other','|Cecum Landmark|Other','|Other','|Other','|Other', '|Other']}) df = pd.concat([task1, task2], join = 'outer', axis = 1)
- 核心需求:无需手动指定列名,自动逐列返回匹配指定正则的行索引列表,预期结果为
task1对应[2,3,4,5]、task2对应[0,1,2,3],同时需要更高效的实现方案。 - 原有实现缺陷:按行遍历性能差,必须手动指定列名才能提取结果,正则写法冗余,存在空值时容易触发报错。
最优实现方案
首先优化正则表达式,将原有的双分支匹配简化为r'\|Cecum Landmark(\||$)',匹配|Cecum Landmark后接竖线或字符串结尾的场景,逻辑更严谨无冗余。
全量实现代码如下:
# 定义匹配规则 pat = r'\|Cecum Landmark(\||$)' # 按列做向量化字符串匹配,得到布尔掩码 match_mask = df.apply(lambda col: col.str.contains(pat, regex=True, na=False)) # 逐列提取匹配为True的行索引,自动适配所有列 res = {col: match_mask.index[match_mask[col]].tolist() for col in df.columns}
运行后res输出为:
{'task1': [2, 3, 4, 5], 'task2': [0, 1, 2, 3]}
完全符合预期结果。
方案优化点
- 自动适配所有列:不需要手动输入列名,后续DataFrame新增列也能自动计算对应结果
- 性能更高:改为按列遍历,依托pandas原生向量化字符串运算,比原有按行遍历的实现性能提升明显,数据量越大优势越突出
- 鲁棒性更强:新增
na=False参数,列中存在空值时也能正常返回False,不会出现NaN导致索引筛选报错 - 正则更简洁严谨:去掉原正则的冗余或逻辑,用后缀匹配统一覆盖两种场景,减少正则回溯,匹配效率更高
内容的提问来源于stack exchange,提问作者TeoK
相关产品推荐
相关产品推荐

