У меня есть список, содержащий несколько слов, и мне нужно извлечь совпадающие слова из текстовой строки, я нашел это, но он извлекает только одно слово.
содержимое файла ключей
это ключевое слово
содержимое файла 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|
+--------------------+-----------------+
я бы хотел
вернуть все подходящие ключевые слова и их количество
и если 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)
@cronoik, я обновил вопрос
Что вы хотите, чтобы произошло, когда строка содержит «ключевое слово ключевое слово»?
Кстати. regexp_extract_all еще не выпущен, поэтому необходимо обходное решение.
Мне удалось решить эту проблему, используя вместо этого 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 thestr
that match theregexp
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.
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 для извлечения хэштега.
Не могли бы вы объяснить 1. немного больше? Как должен выглядеть окончательный фрейм данных? Сколько у вас ключевых слов?