我有一个包含 4 列的数据框,col4 是一个包含文本和数字的字符串:
Col1 Col2 Col3 Col4
Syslog 2016,09,17 1 PD380_003 %LINK-3-UPDOWN
Syslog 2016,09,17 1 NM380_005 %BGP-5-NBR_RESET
Syslog 2016,09,14 1 NM380_005 %BGP-5-NBR_RESET
Syslog 2016,09,08 1 DO NOT TICKET LO380_004 %SYS-5-CONFIG_I Config
我需要保留该列的一个子字符串并删除任何其他内容,所以我使用了正则表达式并制作了一个模式,但是当我运行以下查询时,结果不是我想要的,它用模式本身替换了所有内容:
data.replace({'Col4':{'.*':'([A-Z]{2}[0-9]{3}_[0-9]{3})'}},regex=True)
期望的结果是:
Col1 Col2 Col3 Col4
Syslog 2016,09,17 1 PD380_003
Syslog 2016,09,17 1 NM380_005
Syslog 2016,09,14 1 LO380_004
Syslog 2016,09,08 1 LO380_004
但我得到的结果是这样的:
Col1 Col2 Col3 Col4
Syslog 2016,09,17 1 ([A-Z]{2}[0-9]{3}_[0-9]{3})
Syslog 2016,09,17 1 ([A-Z]{2}[0-9]{3}_[0-9]{3})
Syslog 2016,09,14 1 ([A-Z]{2}[0-9]{3}_[0-9]{3})
Syslog 2016,09,08 1 ([A-Z]{2}[0-9]{3}_[0-9]{3})
我做错了什么?
最佳答案
首先,您在错误的位置使用了错误的正则表达式。 .replace 的 to_replace
参数需要匹配要替换的内容和要删除的内容。所以在这种情况下,你需要在正则表达式前面有一个 ^.*
,在正则表达式后面有一个 .*$
,因为你想在匹配之外修剪字符串:
^.*([A-Z]{2}[0-9]{3}_[0-9]{3}).*$
其次,replace
参数,如果是正则表达式,则需要是捕获组或固定字符串。在这种情况下,\1
就可以了。
最后,.replace
的 Series 形式有更简单的语法(至少对我而言)易于理解。
因此给定:
>>> df
Col1 Col2 Col3 Col4
0 SysLog 2016,09,17 1 PD380_003 %LINK-3-UPDOWN
1 SysLog 2016,09,17 1 NM380_005 %BGP-5-NBR_RESET
2 SysLog 2016,09,17 1 NM380_005 %BGP-5-NBR_RESET
3 SysLog 2016,09,17 1 DO NOT TICKET LO380_004 %SYS-5-CONFIG_I Config
你可以这样做:
>>> df['Col4'].replace(to_replace='^.*([A-Z]{2}[0-9]{3}_[0-9]{3}).*$', value=r'\1', regex=True)
0 PD380_003
1 NM380_005
2 NM380_005
3 LO380_004
Name: Col4, dtype: object
如果更简单,您还可以使用位置参数版本:
df['Col4'].replace('^.*([A-Z]{2}[0-9]{3}_[0-9]{3}).*$', r'\1', regex=True)
但您需要 regex=True
,因为替换字符串将被解释为正则表达式——而不仅仅是静态字符串。
最后直接赋值给原件:
>>> df['Col4']=df['Col4'].replace('^.*([A-Z]{2}[0-9]{3}_[0-9]{3}).*$', r'\1', regex=True)
>>> df
Col1 Col2 Col3 Col4
0 SysLog 2016,09,17 1 PD380_003
1 SysLog 2016,09,17 1 NM380_005
2 SysLog 2016,09,17 1 NM380_005
3 SysLog 2016,09,17 1 LO380_004
关于python - 使用正则表达式替换 DataFrame 中的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39965414/