【问题标题】:Extract numbers from "dd.dd AAA dd.dd BBB" or "AAA dd.dd BBB dd.dd"从“dd.dd AAA dd.dd BBB”或“AAA dd.dd BBB dd.dd”中提取数字
【发布时间】:2019-10-04 08:01:54
【问题描述】:

我正在尝试从任意文本中提取两个值,以多种方式格式化。这两个值是不同的,我想根据附近的环来区分它们,比如说“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 函数解决这个问题,我也愿意接受。

【问题讨论】:

  • 一共有多少个案例(你能一一列举)?
  • 我猜真的有4个案例。 “EEG dd.dd DDT dd.dd”、“dd.dd EEG dd.dd DDT”。 “DDT dd.dd EEG dd.dd”、“dd.dd DDT dd.dd EEG”。为每个创建单独的正则表达式的问题是我仍然需要区分每种情况。我不知道这是否可以比我幼稚的价值提取功能更有效。

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


【解决方案1】:

至少对于这些情况,您可以尝试以下方法:

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

要摆脱 N/A,您可以申请 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 之一)...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-31
    相关资源
    最近更新 更多