Spark 在列中保留与列表匹配的单词
Spark keeping words in column that match a list
我目前有一个列表和一个 Spark 数据框:
['murder', 'violence', 'flashback', 'romantic', 'cult', 'revenge', 'psychedelic', 'comedy', 'suspenseful', 'good versus evil']
我很难想出一种方法来在数据框中创建一个新列,该列从每一行的 tags 列中获取第一个匹配的单词并将其放入为该行新创建的列。
例如,假设标签列中的第一行只有“谋杀”,我希望它显示在新列中。然后,如果下一行中有“无聊”、“愚蠢”和“邪教”,我希望它在新列中显示邪教,因为它与列表匹配。如果标签列的最后一行有“revenge”、“cult”,我希望它只显示 revenge,因为它是匹配列表的第一个词。
您可以使用 PySpark UDF(用户定义函数)。
首先,让我们编写一个python函数来查找列表(在本例中为您提供的列表)和字符串之间的第一个匹配项,即标签列的值:
def find_first_match(tags):
first_match = ''
genres= ['murder', 'violence', 'flashback', 'romantic', 'cult', 'revenge', 'psychedelic', 'comedy', 'suspenseful', 'good versus evil']
for tag in tags.split():
for genre in genres:
if tag==genre:
first_match=tag
return first_match
然后,我们需要将此函数转换为 PySpark udf,以便我们可以将其与 .withColumn() 操作结合使用:
find_first_matchUDF = udf(lambda z:find_first_match(z))
现在我们可以应用udf函数来生成一个新的列。假设 df 是您的 DataFrame 的名称:
from pyspark.sql.functions import col
new_df = df.withColumn("first_match", find_first_matchUDF(col("tags")))
此方法仅在 tags 列中的所有标记都由空格分隔时才有效。
P.S
您可以使用注释避免第二步:
from pyspark.sql.functions import col
@udf(returnType=StringType())
def find_first_match(tags):
first_match = ''
genres= ['murder', 'violence', 'flashback', 'romantic', 'cult', 'revenge', 'psychedelic', 'comedy', 'suspenseful', 'good versus evil']
for tag in tags.split():
for genre in genres:
if tag==genre:
first_match=tag
return first_match
new_df = df.withColumn("first_match", find_first_match(col("tags")))
from pyspark.sql import functions as F
df = spark.createDataFrame([('murder',), ('boring silly cult',), ('revenge cult',)], ['tags'])
mylist = ['murder', 'violence', 'flashback', 'romantic', 'cult', 'revenge', 'psychedelic', 'comedy', 'suspenseful', 'good versus evil']
pattern = '|'.join([f'({x})' for x in mylist])
df = df.withColumn('first_from_list', F.regexp_extract('tags', pattern, 0))
df.show()
# +-----------------+---------------+
# | tags|first_from_list|
# +-----------------+---------------+
# | murder| murder|
# |boring silly cult| cult|
# | revenge cult| revenge|
# +-----------------+---------------+
我目前有一个列表和一个 Spark 数据框:
['murder', 'violence', 'flashback', 'romantic', 'cult', 'revenge', 'psychedelic', 'comedy', 'suspenseful', 'good versus evil']
我很难想出一种方法来在数据框中创建一个新列,该列从每一行的 tags 列中获取第一个匹配的单词并将其放入为该行新创建的列。
例如,假设标签列中的第一行只有“谋杀”,我希望它显示在新列中。然后,如果下一行中有“无聊”、“愚蠢”和“邪教”,我希望它在新列中显示邪教,因为它与列表匹配。如果标签列的最后一行有“revenge”、“cult”,我希望它只显示 revenge,因为它是匹配列表的第一个词。
您可以使用 PySpark UDF(用户定义函数)。
首先,让我们编写一个python函数来查找列表(在本例中为您提供的列表)和字符串之间的第一个匹配项,即标签列的值:
def find_first_match(tags):
first_match = ''
genres= ['murder', 'violence', 'flashback', 'romantic', 'cult', 'revenge', 'psychedelic', 'comedy', 'suspenseful', 'good versus evil']
for tag in tags.split():
for genre in genres:
if tag==genre:
first_match=tag
return first_match
然后,我们需要将此函数转换为 PySpark udf,以便我们可以将其与 .withColumn() 操作结合使用:
find_first_matchUDF = udf(lambda z:find_first_match(z))
现在我们可以应用udf函数来生成一个新的列。假设 df 是您的 DataFrame 的名称:
from pyspark.sql.functions import col
new_df = df.withColumn("first_match", find_first_matchUDF(col("tags")))
此方法仅在 tags 列中的所有标记都由空格分隔时才有效。
P.S
您可以使用注释避免第二步:
from pyspark.sql.functions import col
@udf(returnType=StringType())
def find_first_match(tags):
first_match = ''
genres= ['murder', 'violence', 'flashback', 'romantic', 'cult', 'revenge', 'psychedelic', 'comedy', 'suspenseful', 'good versus evil']
for tag in tags.split():
for genre in genres:
if tag==genre:
first_match=tag
return first_match
new_df = df.withColumn("first_match", find_first_match(col("tags")))
from pyspark.sql import functions as F
df = spark.createDataFrame([('murder',), ('boring silly cult',), ('revenge cult',)], ['tags'])
mylist = ['murder', 'violence', 'flashback', 'romantic', 'cult', 'revenge', 'psychedelic', 'comedy', 'suspenseful', 'good versus evil']
pattern = '|'.join([f'({x})' for x in mylist])
df = df.withColumn('first_from_list', F.regexp_extract('tags', pattern, 0))
df.show()
# +-----------------+---------------+
# | tags|first_from_list|
# +-----------------+---------------+
# | murder| murder|
# |boring silly cult| cult|
# | revenge cult| revenge|
# +-----------------+---------------+