#python #pandas
#python #pandas
Вопрос:
У меня есть фрейм данных с 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})
что я делаю не так?
Комментарии:
1. можете ли вы опубликовать свой
data
DF перед заменой?2. да, пожалуйста, проверьте это еще раз.
Ответ №1:
Во-первых, у вас неправильные регулярные выражения в неправильных позициях. to_replace
Аргумент .replace должен соответствовать тому, что нужно заменить, а что удалить. Итак, в этом случае вам нужно a ^.*
перед и a .*$
за вашим регулярным выражением, поскольку вы хотите обрезать строку вне соответствия:
^.*([A-Z]{2}[0-9]{3}_[0-9]{3}).*$
Во-вторых, replace
аргумент, если это регулярное выражение, должен быть группой захвата или фиксированной строкой. В этом случае 1
подойдет.
Наконец, форма серии .replace
имеет более простой синтаксис (по крайней мере, для меня) для понимания.
Итак, учитывая:
>>> 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
Комментарии:
1. спасибо за объяснение, я новичок в Panda, это объяснение помогает 🙂
Ответ №2:
Я думаю, вам нужно extract
:
data.Col4 = data.Col4.str.extract('([A-Z]{2}[0-9]{3}_[0-9]{3})', expand=False)
print (data)
Col1 Col2 Col3 Col4
0 Syslog 2016,09,17 1 PD380_003
1 Syslog 2016,09,17 1 NM380_005
2 Syslog 2016,09,14 1 NM380_005
3 Syslog 2016,09,08 1 LO380_004
Комментарии:
1. да, это работает, но мне просто интересно, почему replace не может прочитать регулярное выражение?
2. Хм, я проверяю документы , и это может сработать.
3. Но я думаю, что это ошибка.
Ответ №3:
Вы неправильно использовали регулярные выражения.
{'Col4':{'.*':'([A-Z]{2}[0-9]{3}_[0-9]{3})'}}
— означает замену любой строки в Col4
столбце на '([A-Z]{2}[0-9]{3}_[0-9]{3})'
Попробуйте это:
In [87]: df.replace({'Col4':{r'.*?([A-Z]{2}[0-9]{3}_[0-9]{3}).*':r'1'}}, regex=True)
Out[87]:
Col1 Col2 Col3 Col4
0 Syslog 2016,09,17 1 PD380_003
1 Syslog 2016,09,17 1 NM380_005
2 Syslog 2016,09,14 1 NM380_005
3 Syslog 2016,09,08 1 LO380_004