根据相同字符的不同位置将正则表达式应用于熊猫列

Posted

技术标签:

【中文标题】根据相同字符的不同位置将正则表达式应用于熊猫列【英文标题】:Applying regex to pandas column based on different pos of same character 【发布时间】:2021-07-07 10:09:33 【问题描述】:

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

tdf = pd.DataFrame('text_1':['value: 1.25MG - OM - PO/TUBE - ashaf', 'value:2.5 MG - OM - PO/TUBE -test','value: 18 UNITS(S)','value: 850 MG - TDS AFTER FOOD - SC (SUBCUTANEOUS) -had', 'value: 75 MG - OM - PO/TUBE'])

我想应用正则表达式并根据下面给出的规则创建两列

col val 应该存储value: 之后和first hyphen 之前的所有文本

col Adm 应该存储third hyphen 之后的所有文本

我尝试了以下方法,但它不能正常工作

tdf['text_1'].str.findall('[.0-9]+\s*[mgMG/lLcCUNIT]+')

【问题讨论】:

【参考方案1】:

对于您显示的示例,您能否尝试以下操作。

tdf[["val", "Adm"]] = tdf["text_1"].str.extract(r'^value:\s?(\S+(?:\s[^-]+)?)(?:\s-\s.*?-([^-]*)(?:-.*)?)?$', expand=True)
tdf

Online demo for above regex

输出如下。

                                                    text_1          val                  Adm
0                     value: 1.25MG - OM - PO/TUBE - ashaf       1.25MG             PO/TUBE 
1                        value:2.5 MG - OM - PO/TUBE -test       2.5 MG             PO/TUBE 
2                                       value: 18 UNITS(S)  18 UNITS(S)                  NaN
3  value: 850 MG - TDS AFTER FOOD - SC (SUBCUTANEOUS) -had       850 MG   SC (SUBCUTANEOUS) 
4                              value: 75 MG - OM - PO/TUBE        75 MG              PO/TUBE

说明:为上述添加详细说明。

^value:\s?       ##Checking if value starts from value: space is optional here.
(\S+             ##Starting 1st capturing group from here and matching all non space here.
  (?:\s[^-]+)?   ##In a non-capturing group matching space till - comes keeping it optional.
)                ##Closing 1st capturing group here.
(?:\s-\s.*?-     ##In a non-capturing group matching space-space till - first occurrence.
  ([^-]*)        ##Creating 2nd capturing group which has values till next - here.
  (?:-.*)?       ##In a non capturing group from - till end of value keeping it optional.
)?$              ##Closing non-capturing group at the end of the value here.

【讨论】:

@TheGreat,请告诉我它不适用于哪些样本。您展示的样品对我来说效果很好。 哦,抱歉,我以为您阅读了我对上一个答案的评论。我现在更新了我的示例数据框。 抱歉,奖励解决方案不适用于更新后的示例【参考方案2】:

Series.str.extract

tdf['text_1'].str.extract(r'^value:\s?([^-]+)(?:\s-.*?-\s)?([^-]*)(?:\s|$)')

             0                  1
0       1.25MG            PO/TUBE
1       2.5 MG            PO/TUBE
2  18 UNITS(S)                   
3       850 MG  SC (SUBCUTANEOUS)
4        75 MG            PO/TUBE

正则表达式详细信息:

^ : 在行首断言位置 value::匹配字符序列value: \s?:匹配零到一次之间的任何空白字符 ([^-]+) :第一个捕获组匹配除- 之外的任何字符一次或多次 (?:\s-.*?-\s)? : 零和一次之间的非捕获组匹配 \s: 匹配单个空白字符 - :匹配字符 - .*? :匹配零次到无限次之间的任何字符,但尽可能少地匹配 - :匹配字符 - \s : 匹配单个空白字符 ([^-]*) :第二个捕获组匹配除- 之外的任何字符零次或多次 (?:\s|$) :非捕获组 \s- : 匹配单个空白字符 |:或者切换 $ : 在行尾断言位置

See the online Regex demo

【讨论】:

【参考方案3】:

你可以使用

tdf[["val", "Adm"]] = tdf["text_1"].str.extract(r'^val:\s*([^-]*?)(?:\s*-[^-]*-\s*(.*))?$', expand=True)
# => >>> tdf
                                             text_1          val  \
0                        val: 1.25MG - OM - PO/TUBE       1.25MG   
1                         val:2.5 MG - OM - PO/TUBE       2.5 MG   
2                                  val: 18 UNITS(S)  18 UNITS(S)   
3  val: 850 MG - TDS AFTER FOOD - SC (SUBCUTANEOUS)       850 MG   
4                         val: 75 MG - OM - PO/TUBE        75 MG   


0            PO/TUBE  
1            PO/TUBE  
2                NaN  
3  SC (SUBCUTANEOUS)  
4            PO/TUBE  

请参阅regex demo。

详情

^val: - val: 在字符串的开头(如果 val: 并不总是在字符串的开头,请删除 ^ 锚点) \s* - 零个或多个空格 ([^-]*?) - 第 1 组:- 以外的任何字符尽可能少 (?:\s*-[^-]*-\s*(.*))? - 可选序列 \s* - 零个或多个空格 -[^-]*- - 一个-,除- 之外的任何零个或多个字符,然后是- \s* - 零个或多个空格 (.*) - 第 2 组:线路的其余部分 $ - 字符串结束。

【讨论】:

一个小问题。假设我想对列重新排序。意思是,Adm 应该排在第一位,val 应该排在最后一列。正则表达式会保持不变吗? 抱歉,我不在办公桌前,无法尝试 @TheGreat 解压后可以reorder the columns,添加tdf = tdf[['text_1', 'Adm', 'val']]这一行。 谢谢,最后一个问题。我正在尝试更改您的正则表达式以选择3rd hyphen 之后但4th hyphen 之前的所有文本......所以,我写了下面的tdf["text_1"].str.extract(r'^value:\s*([^-]*?)(?:\s*-[^-]*-\s*(.*))?[^-]*', expand=True) 但这似乎给出了不正确的输出。你能帮忙吗? @TheGreat 那将是^val:\s*([^-]*?)(?:\s*-[^-]*-\s*([^-]*)),请参阅demo。

以上是关于根据相同字符的不同位置将正则表达式应用于熊猫列的主要内容,如果未能解决你的问题,请参考以下文章

带有熊猫列的正则表达式

通过正则表达式将熊猫列替换为自身的一个子集

熊猫使用正则表达式选择列并按值除

如何在不同情况下使用正则表达式修改熊猫中的字符串

Pandas 正则表达式拆分字符和组

将多个正则表达式应用于 DataTable 列