我正在尝试从任意文本中提取两个值,这些值以可变方式设置格式。这两个值是不同的,我想根据附近的分数来区分它们,让我们说“ 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函数来解决此问题,我也欢迎那些人。
答案 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之一)...