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