具有布尔列表理解的Spark Dataframe 过滤器

rbl8hiat  于 2023-01-13  发布在  Apache
关注(0)|答案(1)|浏览(127)

我想根据几个非空列过滤spark Dataframe sdf
假设我有:

labels = ["A", "B, C"]

这是可行的:

sdf.where(sf.col(labels[0]).isNotNull() | sf.col(labels[1]).isNotNull() | sf.col(labels[2]).isNotNull())

但是,如果列表很长,我想做一些类似于列表解析的事情:

sdf.where(any([sf.col(l).isNotNull() for l in labels]))

(this不起作用,{ValueError}无法将列转换为布尔值:请使用'&'表示'和','|“”表示“或”,“~”表示“not”。)
我怎样才能做到这一点?

dly7yett

dly7yett1#

您可以使用functools中的reduce来迭代列列表并应用您的逻辑。
在您的示例中,看起来像是要获取其中任何列都具有非空值的所有行(因此应该过滤掉所有空值行)。

from functools import reduce
import pyspark.sql.functions as F

labels = ["A", "B", "C"]

df = spark.createDataFrame(
    [
        (None, 1,    "ABC"),
        (1,    None, "BCD"),
        (None, None, None),
        (2,    2,    None),
        (1,    3,    "DEF"),
        (2,    1,    "EFG"),
        (None, None, None),
        (2,    2,    None),
        (None, 3,    "HIJ"),
        (None, None, None),
        (2,    2,    None),
        (3,    1,    "EFG"),
        (3,    2,    None),
        (None, None, None),
        (2,    2,    None),
        (3,    3,    "HIJ"),
    ],
    ["A", "B", "C"]
)

df.filter(reduce(lambda x, y: x | y,  (F.col(x).isNotNull() for x in labels))).show()
+----+----+----+
|   A|   B|   C|
+----+----+----+
|null|   1| ABC|
|   1|null| BCD|
|   2|   2|null|
|   1|   3| DEF|
|   2|   1| EFG|
|   2|   2|null|
|null|   3| HIJ|
|   2|   2|null|
|   3|   1| EFG|
|   3|   2|null|
|   2|   2|null|
|   3|   3| HIJ|
+----+----+----+

如您所见,所有null值的行都被正确地过滤掉了,这是通过对isNotNull()条件进行OR运算来完成的。

相关问题