使用 PySpark DataFrame 计算列中值列表的出现次数

Count occurrences of list of values in column using PySpark DataFrame

我有一个带有字符串列 text 和一个单独列表 word_list 的 PySpark DataFrame,我需要计算每个 text 中出现了多少 word_list 值]行(可以多次统计)

df = spark.createDataFrame(
  [(1,'Hello my name is John'), 
   (2,'Yo go Bengals'), 
   (3,'this is a text')
  ]
  , ['id','text']
)

word_list = ['is', 'm', 'o', 'my']

结果将是:

| text                  | list_count   |
| Hello my name is John |       6      |
| Yo go Bengals         |       2      |
| this is a text        |       2      | 

对于文本的第一个值,“is”出现一次,“m”出现两次,“o”出现两次,“my”出现一次。在第二行中,word_list 中出现的唯一值是“o”,并且出现了两次。在 text 的第三个值中,word_list 中出现的唯一值是“is”,并且出现了两次。

结果也不一定必须是基于 PySpark 的,如果这样更容易,它可以在 Pandas 中。

您可以使用如下 UDF 执行此操作

UDF

df = sql.createDataFrame(
  [(1,'Hello my name is John'), 
   (2,'Yo go Bengals'), 
   (3,'this is a text')
  ]
  , ['id','text']
)

word_list = ['is', 'm', 'o', 'my']

def count_values(inp,map_list=None):
    
    count = 0
    
    for pattern in map_list:
        if re.findall(pattern,inp):
            count += 1
    
    return count

count_values_udf = F.udf(partial(count_values,map_list=word_list),IntegerType())

df.select(
            count_values_udf(F.col('text')).alias('count_values')
         ).show()

+------------+
|count_values|
+------------+
|           4|
|           1|
|           1|
+------------+

要计算字符串列中子字符串的出现次数,您可以按子字符串拆分该列。计数对应于结果数组的大小减 1。

因此,在您的情况下,您可以在 word_list 数组列上使用 aggregate 函数,并且对于每个元素,拆分 text 列并获得 size - 1

from pyspark.sql import functions as F

result = df.withColumn(
    "word_list",
    F.array(*[F.lit(x) for x in word_list])
).withColumn(
    "list_count",
    F.expr("aggregate(word_list, 0, (acc, x) -> acc + size(split(text, x)) -1)")
).drop("word_list")

result.show(truncate=False)
#+---+---------------------+----------+
#|id |text                 |list_count|
#+---+---------------------+----------+
#|1  |Hello my name is John|6         |
#|2  |Yo go Bengals        |2         |
#|3  |this is a text       |2         |
#+---+---------------------+----------+