如果你使用的是Spark 2.4+,可以试试SPARK SQL高阶函数filter():
from pyspark.sql import functions as F
>>> df.show(5,0)
+---+--------------------------+
|ID |History |
+---+--------------------------+
|1 |USA|UK|IND|DEN|MAL|SWE|AUS|
|2 |USA|UK|PAK|NOR |
|3 |NOR|NZE |
|4 |IND|PAK|NOR |
+---+--------------------------+
df_new = df.withColumn('data', F.split('History', '\|')) \
.withColumn('cnt', F.expr('size(filter(data, x -> x in ("USA", "IND", "DEN")))'))
>>> df_new.show(5,0)
+---+--------------------------+----------------------------------+---+
|ID |History |data |cnt|
+---+--------------------------+----------------------------------+---+
|1 |USA|UK|IND|DEN|MAL|SWE|AUS|[USA, UK, IND, DEN, MAL, SWE, AUS]|3 |
|2 |USA|UK|PAK|NOR |[USA, UK, PAK, NOR] |1 |
|3 |NOR|NZE |[NOR, NZE] |0 |
|4 |IND|PAK|NOR |[IND, PAK, NOR] |1 |
+---+--------------------------+----------------------------------+---+
在哪里我们首先将字段History拆分成一个名为data的数组列,然后使用过滤函数:
filter(data, x -> x in ("USA", "IND", "DEN"))
只检索满足条件的数组元素:IN ("USA", "IND", "DEN"),之后,我们用size()函数对结果数组进行计数。
更新:添加了另一种使用 array_contains() 的方法,它应该适用于旧版本的 Spark:
lst = ["USA", "IND", "DEN"]
df_new = df.withColumn('data', F.split('History', '\|')) \
.withColumn('Count', sum([F.when(F.array_contains('data',e),1).otherwise(0) for e in lst]))
注意:数组中的重复条目将被跳过,此方法只计算唯一的国家代码。