Извлеките несколько слов, используя regexp_extract в PySpark

У меня есть список, содержащий несколько слов, и мне нужно извлечь совпадающие слова из текстовой строки, я нашел это, но он извлекает только одно слово.

содержимое файла ключей

это ключевое слово

содержимое файла part_description

32015 это ключевое слово привет мир

Код

import pyspark.sql.functions as F

keywords = sc.textFile('file:///home/description_search/keys') #1
part_description =  sc.textFile('file:///description_search/part_description') #2
keywords = keywords.map(lambda x: x.split(' ')) #3
keywords = keywords.collect()[0] #4
df = part_description.map(lambda r: Row(r)).toDF(['line']) #5
df.withColumn('extracted_word', F.regexp_extract(df['line'],'|'.join(keywords), 0)).show() #6

Выходы

+--------------------+--------------+
|                line|extracted_word|
+--------------------+--------------+
|32015   this is a...|          this|
+--------------------+--------------+

Ожидаемый результат

+--------------------+-----------------+
|                line|   extracted_word|
+--------------------+-----------------+
|32015   this is a...|this,is,a,keyword|
+--------------------+-----------------+

я бы хотел

  1. вернуть все подходящие ключевые слова и их количество

  2. и если step #4 самый эффективный способ

Воспроизводимый пример:

keywords = ['this','is','a','keyword']
l = [('32015 this is a keyword hello world'      , ),
('keyword this'      ,   ),
('32015 this is a keyword hello world 32015 this is a keyword hello world'      ,   ),
('keyword keyword'      ,   ),
('is a'      , )]

columns = ['line']

df=spark.createDataFrame(l, columns)

Не могли бы вы объяснить 1. немного больше? Как должен выглядеть окончательный фрейм данных? Сколько у вас ключевых слов?

cronoik 28.05.2019 22:48

@cronoik, я обновил вопрос

Exorcismus 29.05.2019 03:21

Что вы хотите, чтобы произошло, когда строка содержит «ключевое слово ключевое слово»?

cronoik 29.05.2019 14:41

Кстати. regexp_extract_all еще не выпущен, поэтому необходимо обходное решение.

cronoik 29.05.2019 14:43
Почему в 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
4
4 425
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Мне удалось решить эту проблему, используя вместо этого UDF, как показано ниже.

def build_regex(keywords):
    res = '('
    for key in keywords:
        res += '\\b' + key + '\\b|'
    res = res[0:len(res) - 1] + ')'

    return res


def get_matching_string(line, regex):
    matches = re.findall(regex, line)
    return matches if matches else None


udf_func = udf(lambda line, regex: get_matching_string(line, regex),
               ArrayType(StringType()))

df = df.withColumn('matched', udf_func(df['line'], F.lit(build_regex(keywords)))).withColumn('count', F.size('matched'))

Результат

+--------------------+--------------------+-----+
|                line|             matched|count|
+--------------------+--------------------+-----+
|32015    this is ...|[this, is, this, ...|    5|
|12832    Shb is a...|             [is, a]|    2|
|35015    this is ...|          [this, is]|    2|
+--------------------+--------------------+-----+

В Искра 3.1+regexp_extract_all доступно:

regexp_extract_all(str, regexp[, idx]) - Extract all strings in the str that match the regexp expression and corresponding to the regex group index.

Ваш первоначальный вопрос теперь может быть решен следующим образом:

re_pattern = '(' + '|'.join([f'\\\\b{k}\\\\b' for k in keywords]) + ')'
df = df.withColumn('matched', F.expr(f"regexp_extract_all(line, '{re_pattern}', 1)"))
df = df.withColumn('count', F.size('matched'))

df.show()
#+--------------------+--------------------+-----+
#|                line|             matched|count|
#+--------------------+--------------------+-----+
#|32015 this is a k...|[this, is, a, key...|    4|
#|        keyword this|     [keyword, this]|    2|
#|32015 this is a k...|[this, is, a, key...|    8|
#|     keyword keyword|  [keyword, keyword]|    2|
#|                is a|             [is, a]|    2|
#+--------------------+--------------------+-----+

Только не могу понять, сколько побегов требуется. Я попытался извлечь хэш-тег с помощью «#[^ ,\n]+», но не смог и вернулся к UDF.

Philip Mok 18.03.2022 14:38

pyspark REGEXP_EXTRACT_ALL с временным представлением

Создайте временное представление:

df.select("user_id","line").createOrReplaceTempView("temp")

Выберите из временного представления, создайте новое временное представление или набор данных:

spark.sql("SELECT user_id,REGEXP_EXTRACT_ALL(line,'(#[a-zA-Z]+)',1) as MATCHED FROM temp").createOrReplaceTempView("temp2")

В этом примере я использую REGEXP_EXTRACT_ALL для извлечения хэштега.

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