Pandas 正则表达式提取两个不同符号前后的所有内容

Pandas regex to extract everything after and before two different symbols

我有一个如下所示的数据框

df = pd.DataFrame({'person_id': [11,11,11],'text':['DOSE: 667 mg - TDS with food - Inject  hypo > 4 test value here','DOSE: 667 mg - TDS with food - Tube','DOSE: 667 mg - TDS with food - PO'],'Summary':['Test','Test1','Test2']})

从上面的数据框中,我想提取所有

a) 在 DOSE: 之后和第一个连字符 -

之前

b) 再次提取第二个连字符 -.

之后的所有内容

我正在尝试类似下面的操作

df['text'].str.extract('(\d+[A-Za-ZS]*(\-))',expand=True)  # doesn't work 
s1 = df['text'].str.split() # I tried using `str.split`
s1[0][1]  # it goes on like for loop which is not elegant.

可以帮我解决以上问题吗?

我希望我的输出如下所示

你可以使用

import pandas as pd
df = pd.DataFrame({'person_id': [11,11,11],'text':['DOSE: 667 mg - TDS with food - Inject','DOSE: 667 mg - TDS with food - Tube','DOSE: 667 mg - TDS with food - PO'],'Summary':['Test','Test1','Test2']})
df['text'].str.replace(r'^DOSE:\s*([^-]*)-[^-]*-\s*(.*)', r'')
# 0    667 mg Inject
# 1      667 mg Tube
# 2        667 mg PO
# Name: text, dtype: object

正则表达式是

^DOSE:\s*([^-]*)-[^-]*-\s*(.*)

参见regex demo详情:

  • ^DOSE: - DOSE: 在字符串的开头
  • \s* - 0+ 个空格
  • ([^-]*) - 第 1 组(</code> 指的是替换模式中的该组值):除 <code>-
  • 之外的任何 0 个或多个字符
  • - - 一个连字符
  • [^-]* - -
  • 以外的 0+ 个字符
  • - - 一个 -
  • \s* - 0+ 个空格
  • (.*) - 捕获第 2 组( 指的是替换模式中的该组值):除换行字符外的任何零个或多个字符,尽可能多。

让我们使用 str.replace

df.text.str.replace(r'DOSE:\s|\s-\sTDS\swith\sfood\s-','')

如何使用 str.replace.

text 列中选择子字符串

以下是获得预期输出的方法:

>>> df = pd.DataFrame({'person_id': [11,11,11],'text':['DOSE: 667 mg - TDS with food - Inject','DOSE: 667 mg - TDS with food - Tube','DOSE: 667 mg - TDS with food - PO'],'Summary':['Test','Test1','Test2']})
>>> df['text'] = df['text'].str.replace(r'\bDOSE:\s*([^-]*)-[^-]*-\s*(.*)', r'')
>>> print( df.filter(['person_id', 'text', 'Summary']) )
   person_id           text Summary
0         11  667 mg Inject    Test
1         11    667 mg Tube   Test1
2         11      667 mg PO   Test2

Code Demo

您在这里可能不需要正则表达式。您可以使用 str.split() 并加入第 0 项和第 2 项。

df['text_new'] = df.text.apply(lambda x: " ".join(map(x.replace("DOSE: ", "").split("-").__getitem__, [0, 2])))