2

我想在我的数据框中创建一个新的布尔列,它的值来自对同一数据框中其他列的两个条件语句的评估:

columns = ["id", "color_one", "color_two"]
data = spark.createDataFrame([(1, "blue", "red"), (2, "red", None)]).toDF(*columns)

data = data.withColumn('is_red', data.color_one.contains("red") | data.color_two.contains("red"))

除非连续为 NULLcolor_one或NULL,否则这可以正常工作。color_two在这种情况下,is_red也设置NULL为该行而不是trueor false

+-------+----------+------------+-------+
|id     |color_one |color_two   |is_red |
+-------+----------+------------+-------+
|      1|      blue|         red|   true|
|      2|       red|        NULL|   NULL|
+-------+----------+------------+-------+

这意味着如果第一个条件恰好为真(如上面示例的第 2 行),PySpark 正在评估条件语句的所有子句,而不是提前退出(通过短路评估)。

PySpark 是否支持条件语句的短路评估?

同时,这是我想出的一种解决方法,可以对每一列进行空值检查:

from pyspark.sql import functions as F

color_one_is_null = data.color_one.isNull()
color_two_is_null = data.color_two.isNull()
data = data.withColumn('is_red', F.when(color_two_is_null, data.color_one.contains("red"))
                                  .otherwise(F.when(color_one_is_null, data.color_two.contains("red"))
                                              .otherwise(F.when(color_one_is_null & color_two_is_null, F.lit(False))
                                                          .otherwise(data.color_one.contains("red") | data.color_two.contains("red"))))
                      )
4

1 回答 1

4

我不认为 Spark 支持对条件进行短路评估,如此处所述https://docs.databricks.com/spark/latest/spark-sql/udf-python.html#:~:text=Spark%20SQL%20 (包括,短路%E2%80%9D%20语义。

Spark SQL(包括 SQL 和 DataFrame and Dataset API)不保证子表达式的求值顺序。特别是,运算符或函数的输入不必从左到右或以任何其他固定顺序进行评估。例如,逻辑 AND 和 OR 表达式没有从左到右的“短路”语义。

另一种替代方法是创建一个column_onecolumn_two数组,然后使用 SQL评估该数组是否包含“红色”EXISTS

data = data.withColumn('is_red', F.expr("EXISTS(array(color_one, color_two), x -> x = 'red')"))
data.show()
+---+---------+---------+------+
| id|color_one|color_two|is_red|
+---+---------+---------+------+
|  1|     blue|      red|  true|
|  2|      red|     null|  true|
|  3|     null|    green| false|
|  4|   yellow|     null| false|
|  5|     null|      red|  true|
|  6|     null|     null| false|
+---+---------+---------+------+
于 2021-07-14T23:02:06.657 回答