Извлечение подстроки с помощью pandas / regex

Я пытаюсь использовать встроенный метод pandas .str.extract для извлечения подстроки из столбца в импортированном мной фрейме данных. Все записи в столбце имеют следующую структуру:

x.xx% Test1 Test2 Test3 XYZ|ZYX Oct 2018

Таким образом, по сути, это всегда число с плавающей запятой, за которым следует строка (которая не всегда имеет одинаковую длину слов), за которой следует трехбуквенный код, который является либо XYZ, либо ZYX, а затем дата.

Я пытаюсь извлечь Test1, Test2 и Test3 из приведенного выше примера, что означает, что я хочу убрать процент в начале, а там, где происходит XYZ | ZYX, я хочу, чтобы все было после того, как исчезло (включая трехбуквенный код).

Я все утро читал о регулярных выражениях, но я немного изо всех сил пытаюсь создать код с использованием экстракта панд, который может вытащить именно то, что я хочу. Какие-либо предложения? Дальнейшее, что я получил, - это нижеприведенное, где показаны только проценты в начале (я пытался разбить его на три категории):

.str.extract('(\d\.\d+%.)') 
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
4 213
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете использовать шаблон с опережением, чтобы определить, когда прекратить сопоставление.

([\w\s]+?)(?=\w{3}\|)'

Подробности

(               # first capture group
    [\w\s]+?    # match letters or whitespaces
)
(?=             # lookahead
    \w{3}       # fixed length 3 chars
    \|          # literal `|`
)

s = pd.Series(['x.xx% Test1 Test2 Test3 XYZ|ZYX Oct 2018'])
s.str.extract(r'([\w\s]+?)(?=\w{3}\|)', expand=False)

0     Test1 Test2 Test3 
dtype: object

Регулярное выражение, которое вы можете, могло бы быть следующим:

r"(\d\.\d+%.)(.*)\s([A-Z]{3})\s([A-Z]{1}[a-z]{2})\s([0-9]{4}$)"

где \d\.\d+%. соответствует проценту

[A-Z]{3} соответствует буквенному коду

[A-Z]{1}[a-z]{2} соответствует месяцу

[0-9]{4}$ соответствует году, в конце

.* соответствует остальным, следовательно, тестам.

\s соответствует одному пробелу, и это вне совпадений.

Итоговый код может быть примерно таким:

import re

string = "3.14% Test1 Test2 Test3 XYZ Oct 2018"

matches = re.findall(r"(\d\.\d+%.)(.*)\s([A-Z]{3})\s([A-Z]{1}[a-z]{2})\s([0-9]{4}$)", string)[0]

percentage = matches[0] 
mytest = matches[1].split(' ')
letter_code = matches[2]
month = matches[3]
year = matches[4]


print(percentage) # 3.14%
print(mytest) # ['Test1', 'Test2', 'Test3']
print(letter_code) # XYZ
print(month) # Oct
print(year) # 2018

Вы можете попробовать Позитивный просмотр назад:

import re
pattern=r'(?<=%)(\s.+)?XYZ|ZYX'
text = """x.xx% Test1 Test2 Test3 XYZ|ZYX Oct 2018


x.xx% Test1 Test2 Test3 ZYX|XYZ Oct 2018"""

for i in re.findall(pattern,text):
    data=re.sub(re.escape('ZYX|'),' ',i)
    if data.split():
        print(data.split())

выход:

['Test1', 'Test2', 'Test3']
['Test1', 'Test2', 'Test3']

Другие вопросы по теме