在pandas提取中使用正则表达式捕获组匹配单个数字后跟单个字母

2 投票
1 回答
42 浏览
提问于 2025-04-12 16:23

我需要从一个 pandas 的序列中提取符合这个规则的子字符串:"[3-6]X",也就是说要找出像 "3X"、"4X"、"5X" 或 "6X" 这样的字符串,这些字符串可能出现在像 "Hello this is an 6X interesting sentence" 这样的任意句子中。

我花了好几个小时尝试各种解决方案,阅读正则表达式的信息等等。我对正则表达式并不感兴趣,也不会深入理解它,它对我来说只在少数情况下有用。我以前从来没有遇到过这么大的困难,通常我能找到适合我问题的正则表达式,比如匹配电子邮件地址、电话号码等,然后稍微修改一下就能在几秒钟或几分钟内得到解决方案。我不知道我在这里哪里出了问题,是我的正则表达式模式有问题,还是我在 pandas 中使用它的方式不对。我知道 Stack Overflow 是个高水平的地方,可能不应该发这个问题,但我已经花了 3 个小时在阅读和尝试解决方案上,而我在过去的 10 年里每周工作 60 个小时,做类似的工作,从未遇到过这么简单的问题却如此困难。

有效的操作:

df.some_column.str.extract("([3-6])").fillna(False)

df.some_column.str.contains("[3-6]X").fillna(False)

这些代码能找到每个数字出现时的一些匹配,但也有很多不匹配的行。

我尝试过这些(包括在提取之前加上 astype(str),以防这会有影响...),例如,我用很多其他的正则表达式变体,但我觉得列出来没什么帮助,因为它们都不管用。我还尝试过 findallcontains 方法。contains 对 "[3-6]X" 的匹配效果很好,但 findallextract 似乎需要不同的东西才能匹配相同的模式。

无效的操作:

df.some_column.str.extract("([3-6]X)").fillna(False)

df.some_column.str.extract("([3-6]{X})").fillna(False)

df.some_column.str.extract("(\b[3-6])").fillna(False)

我还尝试了一个单词断开,这导致提取失败,尽管我所有的数字实例都是用空格分开的。不知道这是否值得一提,但这让我感到困惑。

最小可重现示例

df = DataFrame({'a': ['sdfasd 3X dsflkjsafd', 'sdfpoiusdf 4X cat dog', 'cat dog hamburger']})

# expected
>>> df[df.a.str.contains("[3-6]X", na=False)].a                                                                                                                                                                                                 
0     sdfasd 3X dsflkjsafd                                                                                                                                                                                                                      
1    sdfpoiusdf 4X cat dog                                                                                                                                                                                                                      
Name: a, dtype: object    

# unexpected, except that the MWE behaves as expected...
>>> df.a.str.extract("([3-6]X)")                                                                                                                                                                                                      
0    3X                                                                                                                                                                                                                                        
1    4X                                                                                                                                                                                                                                        
2    NaN                                                                                                                                                                                                                                        
Name: a, dtype: object   

1 个回答

1

看起来你想用 pd.Series.contains 来生成一个布尔值的掩码:

df = pd.DataFrame(
    {"a": ["sdfasd 3X dsflkjsafd", "sdfpoiusdf 4X cat dog", "cat dog hamburger"]}
)

# make sure you have strings in the column - hence .astype(str)
out = df[df["a"].astype(str).str.contains(r"\b[1-4]X")]
print(out)

输出结果是:

                       a
0   sdfasd 3X dsflkjsafd
1  sdfpoiusdf 4X cat dog

撰写回答