#apache-spark #pyspark #apache-spark-sql
#apache-spark #pyspark #apache-spark-sql
Вопрос:
У меня есть необработанный текст в столбце с именем «сообщение», как показано ниже:
Пример фрейма данных
Date message
2020-11-01 ['some not required text1', 'Startstring ,
'some not required text2', MandatorySubstring , 'some not
required text3', 'ID :AB_CD, 'Stopstring' 'some not
required text4', 'Startstring ID :cd_ab', 'some not
required text5', 'ID :ghed','some not required text6', ID :zyx', 'Stopstring 'some
not required text7']
2020-11-02 ['some not required text8', Startstring 'ID :ABCD',
'some not required text9', 'ID :ED_GH', 'some not
required text10', ID :X_YZ, Stopstring 'some not
required text11', 'Startstring
'some not required text12',MandatorySubstring
'some not required text13', ID :z_yx', 'some not required text14''Stopstring
'some not required text15']
Я ищу, чтобы извлечь строку сразу после ID: между Startstring и Stopstring, если между Startstring и Stopstring существует MandatorySubstring, и отбрасываю идентификаторы, если MandatorySubstring не существует между Startstring и Stopstring . За одну дату может быть несколько таких экземпляров.
Ожидаемый результат:
Date message
2020-11-01 AB_CD
2020-11-02 z_yx
Я попробовал следующий шаблон:
pattern = StartStrings*((?:(?!StartString).)*?MandatoryString 1.*?)s*Stopstring
Это дает мне весь текст между startstring и stoptstring . Я понятия не имею, как извлечь текст сразу после ID: из этого текста сейчас.
Кто-нибудь может предоставить мне шаблон регулярных выражений для этого сценария? Помощь в этом отношении высоко ценится. Спасибо
Комментарии:
1. Я думаю, в вашем примере отсутствуют некоторые заключительные кавычки?
2. Это не должно иметь значения. Тип данных для столбца с именем «сообщение» — str, а все значение перед каждой датой — это всего одна строка (необработанный текст). Надеюсь, это прояснило ваш вопрос?
Ответ №1:
Учитывая текущий ввод, я бы предложил
Startstring(?:(?!Startstring).)*?MandatorySubstring(?:(?!Startstring).)*?,['s]*IDs*:s*([^',]*).*?Stopstring
Смотрите демонстрацию регулярных выражений. Подробные сведения:
Startstring
— разделитель слева(?:(?!Startstring).)*?
— любые нулевые или более символов, каждый из которых не запускает последовательностьStartstring
символовMandatorySubstring
— строка, которая должна присутствовать между левыми и правыми разделителями(?:(?!Startstring).)*?
— любые нулевые или более символов, каждый из которых не запускает последовательностьStartstring
символов,
— запятая['s]*
— ноль или более'
или пробелID
— строкаs*:s*
— двоеточие, заключенное в ноль или более пробелов([^',]*)
— Группа 1: любые нулевые или более символов, кроме'
и,
.*?
— любые нулевые или более символов, кроме символов разрыва строки, как можно меньшеStopstring
— разделитель справа.
Ответ №2:
Мы можем сделать это в три этапа. Сначала используйте регулярное выражение для поиска в этих строках начальной строки, обязательной подстроки и конечной строки. Мы используем утверждения с отрицательным прогнозом, чтобы гарантировать, что обязательная подстрока действительно находится между двумя соседними строками start и stop. Как только у нас есть эти совпадения, мы извлекаем идентификаторы, присутствующие в каждом из них, и, наконец, сводим их в один список.
def extract_ids(s):
matches = re.findall(r'Startstring((?:(?!Startstring).)*)MandatorySubstring((?:(?!Stopstring).)*)Stopstring', s)
all_ids = [re.findall(r'IDs*:([^,]*)', group) for match in matches for group in match]
ids_flat = [i for l in all_ids for i in l]
return ids_flat
s1 = """['some not required text1', 'Startstring , 'some not required text2', MandatorySubstring , 'some not required text3', 'ID :AB_CD, 'Stopstring' 'some not required text4', 'Startstring ID :cd_ab', 'some not required text5', 'ID :ghed','some not required text6', ID :zyx', 'Stopstring 'some not required text7']"""
s2 = """['some not required text8', Startstring 'ID :ABCD', 'some not required text9', 'ID :ED_GH', 'some not required text10', ID :X_YZ, Stopstring 'some not required text11', 'Startstring 'some not required text12',MandatorySubstring 'some not required text13', ID :z_yx', 'some not required text14''Stopstring 'some not required text15']"""
>>> extract_ids(s1)
['AB_CD']
>>> extract_ids(s2)
["z_yx'"]
Чтобы применить это к вашему фрейму данных, просто используйте df['message'].map(extract_ids)
.
Комментарии:
1. Отредактировал мой вопрос для ясности. пожалуйста, посмотрите. Спасибо