PySpark:when子句中的多个条件

Posted

技术标签:

【中文标题】PySpark:when子句中的多个条件【英文标题】:PySpark: multiple conditions in when clause 【发布时间】:2016-10-09 00:07:43 【问题描述】:

我想修改当前为空白的数据框列 (Age) 的单元格值,并且仅当另一列 (Survived) 的相应行的值为 0 时,我才会这样做,而该行的 Age 为空白。如果它在 Survived 列中为 1,但在 Age 列中为空白,那么我将其保留为 null。

我尝试使用&& 运算符,但它不起作用。这是我的代码:

tdata.withColumn("Age",  when((tdata.Age == "" && tdata.Survived == "0"), mean_age_0).otherwise(tdata.Age)).show()

任何建议如何处理?谢谢。

错误信息:

SyntaxError: invalid syntax
  File "<ipython-input-33-3e691784411c>", line 1
    tdata.withColumn("Age",  when((tdata.Age == "" && tdata.Survived == "0"), mean_age_0).otherwise(tdata.Age)).show()
                                                    ^

【问题讨论】:

【参考方案1】:

whenpyspark 中可以使用 &(for and)和 |(for or )。

注意:在 pyspark 中,将每个表达式括在括号 () 中很重要,这些表达式组合形成条件

%pyspark
dataDF = spark.createDataFrame([(66, "a", "4"), 
                                (67, "a", "0"), 
                                (70, "b", "4"), 
                                (71, "d", "4")],
                                ("id", "code", "amt"))
dataDF.withColumn("new_column",
       when((col("code") == "a") | (col("code") == "d"), "A")
      .when((col("code") == "b") & (col("amt") == "4"), "B")
      .otherwise("A1")).show()

在 Spark Scala 代码中 (&&) 或 (||) 条件可以在 when 函数中使用

//scala
val dataDF = Seq(
      (66, "a", "4"), (67, "a", "0"), (70, "b", "4"), (71, "d", "4"
      )).toDF("id", "code", "amt")
dataDF.withColumn("new_column",
       when(col("code") === "a" || col("code") === "d", "A")
      .when(col("code") === "b" && col("amt") === "4", "B")
      .otherwise("A1")).show()

=========================

Output:
+---+----+---+----------+
| id|code|amt|new_column|
+---+----+---+----------+
| 66|   a|  4|         A|
| 67|   a|  0|         A|
| 70|   b|  4|         B|
| 71|   d|  4|         A|
+---+----+---+----------+

这段代码sn-p是从sparkbyexamples.com复制过来的

【讨论】:

【参考方案2】:

它至少应该在 pyspark 2.4 中工作

tdata = tdata.withColumn("Age",  when((tdata.Age == "") & (tdata.Survived == "0") , "NewValue").otherwise(tdata.Age))

【讨论】:

【参考方案3】:

应该是:

$when(((tdata.Age == "" ) & (tdata.Survived == "0")), mean_age_0)

【讨论】:

【参考方案4】:

您会收到 SyntaxError 错误异常,因为 Python 没有 &amp;&amp; 运算符。它有and&amp;,后者是在Column 上创建布尔表达式的正确选择(| 用于逻辑析取,~ 用于逻辑否定)。

您创建的条件也无效,因为它不考虑operator precedence。 Python 中的&amp; 具有比== 更高的优先级,因此表达式必须用括号括起来。

(col("Age") == "") & (col("Survived") == "0")
## Column<b'((Age = ) AND (Survived = 0))'>

附带说明when 函数等效于case 表达式而不是WHEN 子句。仍然适用相同的规则。连词:

df.where((col("foo") > 0) & (col("bar") < 0))

析取:

df.where((col("foo") > 0) | (col("bar") < 0))

您当然可以单独定义条件以避免括号:

cond1 = col("Age") == "" 
cond2 = col("Survived") == "0"

cond1 & cond2

【讨论】:

感谢您对运算符优先级的评论,它解决了我获取日期范围的问题 有效!但在 Spark 中是否记录了布尔表达式(在 wherefilter 等中)的使用? "您创建的条件也是无效的,因为它不考虑运算符优先级。Python 中的 & 具有比 == 更高的优先级,因此必须为表达式加上括号。"非常有帮助的观察

以上是关于PySpark:when子句中的多个条件的主要内容,如果未能解决你的问题,请参考以下文章

Pyspark 中的多个 WHEN 条件实现

如何在 pyspark.sql.functions.when() 中使用多个条件?

如何在pyspark数据框中添加多个带有when条件的新列?

为 pyspark 数据帧的每一行评估多个 if elif 条件

如何在 PySpark SQL when() 子句中使用聚合值?

如何使用给定的reduce函数基于pyspark中的字段合并多个JSON数据行