从“ dd.dd AAA dd.dd BBB”或“ AAA dd.dd BBB dd.dd”中提取数字

时间:2019-05-17 02:27:37

标签: python regex pandas regex-negation regex-lookarounds

我正在尝试从任意文本中提取两个值,这些值以可变方式设置格式。这两个值是不同的,我想根据附近的分数来区分它们,让我们说“ DDT”和“ EEG”。这是一些如何格式化字符串的示例。

This contains 42.121% DDT and 2.1% EEG

Now with DDT: 12% EEG: 23.2%

47 DDT 22 EEG

EEG N/A DDT 43

5% EEG 20% DDT and more

从本质上讲,我需要能够选择两个值,然后分别加上它们的标识符。

我一直在使用|在两个选择器之间捕获每个值的两个“个案”,但是我遇到了麻烦。我想防止正则表达式在第二个示例行中选择“ 12%EEG”。我正在尝试使用消极的前瞻性和积极的后瞻性,但无法使其正常工作。

这里是仅选择ddt的正则表达式

(?<=eeg)(\d{1,3}\.?\d{1,6}).{,10}?ddt|ddt(?!.*eeg).{,10}?(\d{1,3}\.?\d{1,6})

这是我所获得的最接近的结果,但仍然无法正常工作。此版本无法匹配“ 20%DDT”。

我原来的正则表达式没有使用lookbehinds,但在某些情况下也失败了。

(?:(?:(\d{1,3}\.?\d*)[^(?:eeg)]{0,10}?ddt)|(?:ddt[^(?:eeg)]{0,10}?(\d{1,3}\.?\d*)))

我的原始方法无法识别这样格式化的23.2%EEG字符串。 “滴滴涕:12%脑电图:23.2%”

我不确定正则表达式是否可以使用这种选择器,但是我想使用正则表达式来矢量化此提取。我有一个很好的表征这些字符串的函数,但是在大型数据集(约100万条记录)上,它的运行速度非常慢。正则表达式运行速度很快,并且易于应用于向量,这就是为什么我要使用它。如果还有其他建议使用NLP或numpy / pandas函数来解决此问题,我也欢迎那些人。

1 个答案:

答案 0 :(得分:0)

至少在这些情况下,您可以尝试以下操作:

1 /确定是第一个EEG或DDT:

In [11]: s.str.extract("(DDT|EEG)")
Out[11]:
     0
0  DDT
1  DDT
2  DDT
3  EEG
4  EEG

2 /拔出所有数字:

In [12]: s.str.extract("(\d+\.?\d*|N/A).*?(\d+\.?\d*|N/A)")
Out[12]:
        0     1
0  42.121   2.1
1      12  23.2
2      47    22
3     N/A    43
4       5    20

要摆脱不适用的情况,您可以申请to_numeric:

In [13]: res = s.str.extract("(\d+\.?\d*|N/A).*?(\d+\.?\d*|N/A)").apply(pd.to_numeric, errors='coerce', axis=1)

In [14]: res
Out[14]:
        0     1
0  42.121   2.1
1  12.000  23.2
2  47.000  22.0
3     NaN  43.0
4   5.000  20.0

现在,您必须重新排列这些列以匹配其各自的DDT / EEG:

In [15]: pd.DataFrame({
           "DDT": res[0].where(s.str.extract("(DDT|EEG)")[0] == 'DDT', res[1]),
           "EEG": res[1].where(s.str.extract("(DDT|EEG)")[0] == 'DDT', res[0])
         })
Out[15]:
      DDT   EEG
0  42.121   2.1
1  12.000  23.2
2  47.000  22.0
3  43.000   NaN
4  20.000   5.0

s是原始的系列/列:

In [21]: s
Out[21]:
0    This contains 42.121% DDT and 2.1% EEG
1              Now with DDT: 12% EEG: 23.2%
2                             47 DDT 22 EEG
3                            EEG N/A DDT 43
4                   5% EEG 20% DDT and more
dtype: object

这假设DDT和EEG都同时存在,您可能需要在没有这种情况的行中将其NaN排除(它们只有DDT / EEG之一)...