假设我们有一个pyspark数据帧,其中的一列(column_a
)包含一些字符串值,并且还有一个字符串列表(list_a
)。
数据框:
column_a | count
some_string | 10
another_one | 20
third_string | 30
list_a:
['string', 'third', ...]
我要过滤此数据框,并且仅当column_a的值包含list_a的一项时才保留行。
这是用于根据单个字符串过滤column_a
的代码:
df['column_a'].like('%string_value%')
但是我们如何才能得到相同的字符串列表结果呢? (请保留column_a值为'string','third',...的行)
答案 0 :(得分:1)
IIUC,您想返回column_a
中的任何值与list_a
(从SQL角度而言)“相似”的行。
一种方法是使用functools.reduce
:
from functools import reduce
list_a = ['string', 'third']
df1 = df.where(
reduce(lambda a, b: a|b, (df['column_a'].like('%'+pat+"%") for pat in list_a))
)
df1.show()
#+------------+-----+
#| column_a|count|
#+------------+-----+
#| some_string| 10|
#|third_string| 30|
#+------------+-----+
基本上,您循环遍历list_a
中的所有可能的字符串,以对like
进行比较并“或”比较结果。这是执行计划:
df1.explain()
#== Physical Plan ==
#*(1) Filter (Contains(column_a#0, string) || Contains(column_a#0, third))
#+- Scan ExistingRDD[column_a#0,count#1]
另一种选择是使用pyspark.sql.Column.rlike
而不是like
。
df2 = df.where(
df['column_a'].rlike("|".join(["(" + pat + ")" for pat in list_a]))
)
df2.show()
#+------------+-----+
#| column_a|count|
#+------------+-----+
#| some_string| 10|
#|third_string| 30|
#+------------+-----+
有相应的执行计划:
df2.explain()
#== Physical Plan ==
#*(1) Filter (isnotnull(column_a#0) && column_a#0 RLIKE (string)|(third))
#+- Scan ExistingRDD[column_a#0,count#1]