如何在DataFrame中高效提取字符串中的指定关键词(不区分大小写)
高效提取DataFrame字符串中的目标关键词(不区分大小写+忽略空格)
核心需求拆解
要解决的问题是:在大型DataFrame的长字符串列中,快速提取指定关键词列表中的内容,要求:
- 不区分大小写(比如匹配
cookies对应原关键词Cookies) - 不受空格限制(关键词中的空格可匹配任意数量的空白字符)
- 处理长字符串和大数据量时保持高效
方案一:正则+Pandas向量化操作(中小型关键词列表首选)
利用Pandas内置的向量化字符串方法结合正则的不区分大小写模式,性能远高于逐行apply,适合关键词数量不多(几百个以内)的场景。
步骤与代码示例
import pandas as pd import re # 示例输入 keys = ['I', 'love', 'Cookies'] df = pd.DataFrame({ 'text': [ "xxxxxxxxIxx xx cookies", "Love COOKIES today", "No matching words here", "i LOVE chocolate cookies" ] }) # 1. 预处理关键词:转义特殊字符+替换空格为任意空白正则 escaped_keys = [re.escape(key).replace(r'\ ', r'\s*') for key in keys] pattern = '|'.join(escaped_keys) # 2. 建立小写到原关键词的映射(确保返回原关键词格式) key_map = {key.lower(): key for key in keys} # 3. 用extractall批量提取所有匹配项,再分组聚合 extracted_matches = df['text'].str.extractall(f'({pattern})', flags=re.IGNORECASE) extracted_matches = extracted_matches.reset_index() # 映射回原关键词并去重 extracted_matches[0] = extracted_matches[0].str.lower().map(key_map) df['extracted'] = extracted_matches.groupby('level_0')[0].apply(lambda x: list(set(x))) # 填充无匹配的行 df['extracted'] = df['extracted'].fillna(pd.Series([[]], index=df.index)) print(df)
输出结果
text extracted 0 xxxxxxxxIxx xx cookies [I, Cookies] 1 Love COOKIES today [love, Cookies] 2 No matching words here [] 3 i LOVE chocolate cookies [I, love, Cookies]
性能优势
- Pandas的
str.extractall是底层优化的向量化操作,比逐行apply快5-10倍,百万级行数据也能快速处理。 - 正则的
re.IGNORECASE直接处理大小写问题,\s*匹配任意数量的空格/制表符,满足空格无关的要求。
方案二:Aho-Corasick自动机(大型关键词列表首选)
当关键词数量超过1000个时,正则表达式的分支匹配会因回溯导致性能下降,此时用Aho-Corasick多模式匹配算法更高效,时间复杂度为O(n+m)(n为文本长度,m为总关键词长度)。
需要先安装依赖库:pip install pyahocorasick
步骤与代码示例
import pandas as pd import ahocorasick import re # 示例输入 keys = ['I', 'love', 'Cookies'] df = pd.DataFrame({ 'text': [ "xxxxxxxxIxx xx cookies", "Love COOKIES today", "No matching words here", "i LOVE chocolate cookies" ] }) # 1. 预处理:统一去除空格并转小写,用于忽略空格和大小写 def preprocess(s): return re.sub(r'\s+', '', s.lower()) # 2. 构建关键词映射(处理后的关键词→原关键词) processed_key_map = {preprocess(key): key for key in keys} # 3. 构建Aho-Corasick自动机 automaton = ahocorasick.Automaton() for processed_key, original_key in processed_key_map.items(): automaton.add_word(processed_key, original_key) automaton.make_automaton() # 4. 定义提取函数 def extract_keywords(text): processed_text = preprocess(text) matches = set() for _, original_key in automaton.iter(processed_text): matches.add(original_key) return list(matches) # 5. 批量处理DataFrame df['extracted'] = df['text'].apply(extract_keywords) print(df)
输出结果与方案一一致,但处理超大量关键词时性能差距明显。
关键注意事项
- 特殊字符转义:正则方案中必须用
re.escape处理关键词,避免.、*等正则特殊字符破坏匹配规则。 - 去重与顺序:示例中用
set去重,若需要保留匹配的先后顺序,可改用dict.fromkeys(Python 3.7+):list(dict.fromkeys(match_list))。 - 无匹配处理:用
fillna将无匹配的行填充为空列表,避免后续操作出现NaN。
内容的提问来源于stack exchange,提问作者J CB
相关产品推荐
相关产品推荐

