如何基于嵌套列表的多组关键词批量过滤DataFrame文本列
批量实现DataFrame多组关键词过滤方案
核心规则:每个关键词子列表对应一条过滤逻辑,要求transaction_description字段同时命中组内所有关键词,通过动态生成布尔掩码即可完成批量过滤,无需手动硬编码每个关键词判断。
方法1:逐组遍历判断(可读性最高,适配绝大多数场景)
先完成测试数据与依赖初始化:
import pandas as pd from pandas import Timestamp # 初始化待处理DataFrame df_data = [ [5, 56, Timestamp('2022-01-29 00:00:00'), 'pac c.misalud conv. unificado', 12320.0], [5, 57, Timestamp('2021-12-19 00:00:00'), 'cargo seguro proteccion bancaria', 31222.0], [5, 60, Timestamp('2021-04-06 00:00:00'), 'pac sura cia seguros generales', 8657.0], [5, 178, Timestamp('2022-03-21 00:00:00'), 'cargo seguro proteccion bancaria', 31222.0], [5, 179, Timestamp('2022-03-01 00:00:00'), 'pac c.misalud conv. unificado', 12320.0], [5, 182, Timestamp('2022-03-15 00:00:00'), 'pac sura cia seguros generales', 8657.0], [5, 189, Timestamp('2022-04-21 00:00:00'), 'cargo seguro proteccion bancaria', 31222.0], [5, 190, Timestamp('2022-04-01 00:00:00'), 'pac c.misalud conv. unificado', 12320.0], [5, 193, Timestamp('2022-04-15 00:00:00'), 'pac sura cia seguros generales', 8657.0], [5, 206, Timestamp('2022-05-21 00:00:00'), 'cargo seguro proteccion bancaria', 31222.0], [5, 256, Timestamp('2022-06-17 00:00:00'), 'cargo seguro proteccion bancaria', 40222.0] ] kw_df = pd.DataFrame(df_data, columns=['user_id', 'reg_id', 'date', 'transaction_description', 'value']) # 从MySQL读取的嵌套关键词配置 keywords = [ [('tarifa',), ('mantenimiento',), ('mensual',)], [('tasa',), ('anual',)], [('seguro',), ('bancaria',)], [('seguro',), ('generales',)], [('mi salud',), ('unific',)] ]
核心过滤逻辑:
all_matched = [] for rule_id, kw_group in enumerate(keywords): # 提取当前规则组内的关键词(适配单元素元组的存储结构) current_kws = [kw[0] for kw in kw_group] # 初始化布尔掩码为全True,逐关键词做逻辑与运算 mask = pd.Series(True, index=kw_df.index) for kw in current_kws: mask &= kw_df['transaction_description'].str.contains(kw, case=False) # 过滤得到当前规则命中的行,追加规则ID便于后续区分 group_res = kw_df[mask].copy() group_res['match_rule_id'] = rule_id all_matched.append(group_res) # 合并所有命中结果,若存在同一行命中多条规则的情况会保留多条记录 final_result = pd.concat(all_matched, ignore_index=True)
基于提供的测试数据运行后,会命中3组规则:
- 规则ID2(
seguro+bancaria):匹配所有cargo seguro proteccion bancaria记录 - 规则ID3(
seguro+generales):匹配所有pac sura cia seguros generales记录 - 规则ID4(
mi salud+unific):匹配所有pac c.misalud conv. unificado记录
规则ID0、ID1无匹配数据,返回空结果,和手动硬编码的过滤逻辑完全一致。
方法2:正则合并优化(适配10万行以上大数据量场景)
逐关键词调用str.contains会产生多次字符串遍历开销,数据量较大时可将每组关键词拼接为正向预查正则,仅需一次字符串匹配即可完成判断:
import re all_matched = [] for rule_id, kw_group in enumerate(keywords): current_kws = [kw[0] for kw in kw_group] # 拼接为同时匹配所有关键词的正则,re.escape自动转义正则特殊字符 pattern = '^' + ''.join([f'(?=.*{re.escape(kw)})' for kw in current_kws]) mask = kw_df['transaction_description'].str.contains(pattern, case=False, regex=True) group_res = kw_df[mask].copy() group_res['match_rule_id'] = rule_id all_matched.append(group_res) final_result = pd.concat(all_matched, ignore_index=True)
正则逻辑说明:
(?=.*关键词)为正向零宽预查,代表字符串任意位置存在对应关键词,多个预查项拼接即代表同时满足所有关键词存在的要求。
常用配置调整
- 若需关键词匹配区分大小写,将
str.contains的参数case=False改为case=True即可 - 若需匹配完整单词而非子串(例如避免
seguro匹配到seguros),可在关键词两侧添加\b词边界标记,按需调整正则规则即可 - 若仅需返回所有命中的行、不需要区分命中的规则组,合并结果时添加
final_result = final_result.drop_duplicates(subset=['user_id','reg_id'])即可去重
内容的提问来源于stack exchange,提问作者feruciform
相关产品推荐
相关产品推荐

