对于一项作业,我需要在注释中提取所有“提及”。在普通的python中,我会这样做:
string = "@rjberger10 @geneh19 home"
re.findall(r'@\w+', string)
这将给我这样的数组:['@ rjberger10','@ geneh19']。但是赋值指出我们必须使用PySpark方式,但是我在PySpark中找不到类似于findall()的函数。我最接近的是:
result = dict_comments[13].withColumn("@tjes", regexp_extract(col("Text"), r'(@\w+)', 0))
但这只是第一次给我使用@,因此,当有多个提及时,我只会找到一个。
答案 0 :(得分:1)
另一种方法可能是先删除字符串中与模式不匹配的部分,然后在空白处分割其余文本:
from pyspark.sql.functions import col, split, regexp_replace
df.withColumn(
"@tjes",
split(regexp_replace(col("Text"), r'(\s|^)[^@]\w+(\s|$)', ''), '\s+')
).show(truncate=False)
#+-------------------------+-----------------------+
#|Text |@tjes |
#+-------------------------+-----------------------+
#|@rjberger10 @geneh19 home|[@rjberger10, @geneh19]|
#+-------------------------+-----------------------+
regexp_replace
中使用的模式是:
(\s|^)
:空格或字符串开头[^@]
:不是@
字符\w+
:任意数量的文字字符(\s|$)
:空格或字符串结尾答案 1 :(得分:0)
我有一种使用explode
,split
,regexp_extract
和collect_list
的方法。
re_df = spark._sc.parallelize([[1,"@rjberger10"],
[2,"@geneh19"],
[3,"home"],
[4,"@geneh19 @rjberger10"]]).toDF(["id","test_string"])
temp_column_name = "explode_on_split"
(
re_df.withColumn(temp_column_name,
f.explode(f.split(f.col("test_string"), " ")))
.withColumn('extract',
f.regexp_extract(f.col(temp_column_name), r'(@\w+)', 1))
.groupBy(f.col('test_string'))
.agg(
f.collect_list(f.col('extract')).alias('final_extract'))
).show()
+--------------------+--------------------+
| test_string| final_extract|
+--------------------+--------------------+
|@geneh19 @rjberger10|[@geneh19, @rjber...|
| @rjberger10| [@rjberger10]|
| home| []|
| @geneh19| [@geneh19]|
+--------------------+--------------------+
我知道这看起来很麻烦,所以请解释一下: 我在空间上划分,将输出分解为行,用正则表达式扩展输出并按此顺序收集。 但是,如果您查看Spark GitHub页面,您可以期望此功能会在已经有开放的PR(https://github.com/apache/spark/pull/21985)时立即弹出。 希望这会有所帮助!