在 PySpark 中使用 regexp_extract 提取多个单词
Posted
技术标签:
【中文标题】在 PySpark 中使用 regexp_extract 提取多个单词【英文标题】:Extract multiple words using regexp_extract in PySpark 【发布时间】:2019-05-28 12:00:25 【问题描述】:我有一个包含一些单词的列表,我需要从文本行中提取匹配的单词,我找到了this,但它只提取了一个单词。
密钥文件内容
这是一个关键字
part_description 文件内容
32015 这是一个关键字 hello world
代码
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)
【问题讨论】:
你能解释一下 1. 多一点吗?最终的数据框应该是什么样子?你有多少个关键词? @cronoik,我更新了问题 当一行包含'keyword keyword'时你想发生什么? 顺便说一句。 regexp_extract_all 尚未发布,因此需要解决方法。 【参考方案1】:在 Spark 3.1+ 中regexp_extract_all
可用:
regexp_extract_all(str, regexp[, idx])
- 提取str
中与regexp
表达式匹配并对应于正则表达式组索引的所有字符串。
你原来的问题现在可以这样解决:
re_pattern = '(' + '|'.join([f'\\\\bk\\\\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【参考方案2】:我设法通过使用 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】:带有临时视图的 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 来提取主题标签
【讨论】:
以上是关于在 PySpark 中使用 regexp_extract 提取多个单词的主要内容,如果未能解决你的问题,请参考以下文章
Apache Spark:如何在Python 3中使用pyspark