Pandas使用str.contains报nothing to repeat at position 17217错误如何解决?
问题描述
我尝试使用str.contains判断一个DataFrame某列的元素是否存在于另一个DataFrame的指定列中,代码如下:
pattern = fr"(?:{'|'.join(strategic_accounts['Account Name'])})" all_leads['in_strategic_list'] = all_leads['Company'].str.contains(pattern).astype(int)
我已经核对了两个DataFrame的头部数据,以及all_leads DataFrame的第17271位数据,该位置没有异常内容。另外我检索到的同类报错均为position 0的报错,和我遇到的17217位置报错场景不同。
我编写的如下模拟示例使用相同代码可以正常运行:
df1 = pd.DataFrame({'name': ['Marc', 'Jake', 'Sam', 'Brad', 'SpongeBob']}) df2 = pd.DataFrame({'IDs': ['Jake', 'John', 'Marc', 'Tony', 'Bob']}) pattern = fr"(?:{'|'.join(df2['IDs'])})" df1['In_df2'] = df1['name'].str.contains(pattern).astype(int)
问题更新
我已经定位到报错指向的是pattern字符串的第17217位,而非strategic_accounts DataFrame的对应位置,打印该位置字符返回'*'。我尝试自定义函数处理pattern中的特殊字符后再传入str.contains,但特殊字符没有被成功替换,处理代码如下:
import re pattern = fr"(?:{'|'.join(strategic_accounts['Account Name'])})" def esc_spec_char(pattern): for p in pattern: if p == '\*': re.sub('*', '1', p) else: continue return pattern pattern = esc_spec_char(pattern) pattern[17217]
最新更新
我尝试采用@LiamFiddler提供的方法,将字符串转为re.Pattern对象后在模拟数据集上测试,虽然*被成功转义,但无法匹配到字符N,不确定哪里出现错误,测试代码如下:
sries = pd.Series(['x','y','$','%','^','N','*']) ac = '|'.join(sries) p = re.compile(re.escape(ac)) df1 = pd.DataFrame(data = {'Id' : [123, 232, 344, 455, 566, 377], 'col2' : ["N", "X", "Y", '*', "W", "Z"]}) df1['col2'].str.contains(p, regex=True).astype(int)
解决方案
报错的核心原因是你用于拼接正则的账户名称中包含*这类正则保留特殊字符,直接拼接会被正则引擎解析为语法符号,导致编译报错。你之前的两次尝试都存在逻辑错误:
- 自定义转义函数完全不生效:循环遍历字符时没有对原字符串做修改,re.sub的返回值没有被接收,判断逻辑也存在语法错误。
- 转义位置错误:你先将所有关键词用
|拼接后再整体转义,会把用于表示「或匹配」的|也转义为普通字符,自然无法匹配到对应的关键词。
正确的处理逻辑是:先对每个单独的关键词做正则特殊字符转义,再用|拼接成正则模式,既能保留或匹配的逻辑,又能把特殊字符作为普通文本匹配。
修复后的代码
原始需求代码
import pandas as pd import re # 对每个账户名单独转义正则特殊字符 escaped_accounts = strategic_accounts['Account Name'].apply(lambda x: re.escape(str(x))) # 拼接成正则模式 pattern = fr"(?:{'|'.join(escaped_accounts)})" # 执行匹配 all_leads['in_strategic_list'] = all_leads['Company'].str.contains(pattern, regex=True).astype(int)
测试用例修复代码
import pandas as pd import re sries = pd.Series(['x','y','$','%','^','N','*']) # 先转义每个关键词再拼接 escaped_keys = sries.apply(lambda x: re.escape(str(x))) pattern = '|'.join(escaped_keys) p = re.compile(pattern) df1 = pd.DataFrame(data = {'Id' : [123, 232, 344, 455, 566, 377], 'col2' : ["N", "X", "Y", '*', "W", "Z"]}) print(df1['col2'].str.contains(p, regex=True).astype(int))
运行后输出为[1,0,0,1,0,0],完全符合预期。
内容的提问来源于stack exchange,提问作者Justin Benfit
相关产品推荐
相关产品推荐

