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

39

我有一个数据框有几列,现在我想从另外两列中派生出一个新列:

from pyspark.sql import functions as F
new_df = df.withColumn("new_col", F.when(df["col-1"] > 0.0 & df["col-2"] > 0.0, 1).otherwise(0))

我只得到一个异常:

py4j.Py4JException: Method and([class java.lang.Double]) does not exist

只要满足以下一个条件,它就可以正常工作:

new_df = df.withColumn("new_col", F.when(df["col-1"] > 0.0, 1).otherwise(0))

有人知道如何使用多条件吗?

我正在使用Spark 1.4。


在Python中,你不应该写成 df["col-1"] > 0.0 and df["col-2"]>0.0 吗? - Ashalynd
6
不行,这会导致以下错误:ValueError: 无法将列转换为布尔值:在构建DataFrame布尔表达式时,请使用 '&' 表示 'and', '|' 表示 'or','~' 表示 'not'。 - jho
4
我明白了,那么我想你需要使用括号:(df["col-1"] > 0.0) & (df["col-2"] > 0.0),以解决优先级问题。 - Ashalynd
很奇怪,我很确定我测试过了,但现在它却可以工作了。谢谢! :) - jho
1
@Ashalynd 请将其发布为答案。 - zero323
@AlbertoBonsanto 它是如何解决这个问题的?它只是因为运算符优先级需要括号。 - zero323
3个回答

71

使用括号来强制执行所需的运算符优先级:

F.when( (df["col-1"]>0.0) & (df["col-2"]>0.0), 1).otherwise(0)

1
以上解决方案对我有效。请注意数据类型。当我尝试执行 df["col-2"] is not None 时,我遇到了错误 py4j.Py4JException: Method and([class java.lang.Boolean]) does not exist。Pyspark关心数据类型,因为我的 col-2 是字符串,所以我必须执行 df["col-2"] == '' - Will

21

pyspark 中,可以使用&(表示 and)和|(表示 or)来构建多个条件。重要的是,将组成条件的每个表达式都括在圆括号内。

%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()

when 可以与 &&|| 运算符一起使用,在spark scala中构建多个条件。

//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()

输出:

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

这在PySpark中是无效的 - 虽然我猜其他变体的Spark可能是有效的? - Marco
1
@Marco 谢谢,我改正了。更新的 Pyspark 代码片段。 - vj sreenivasan

3

您还可以使用from pyspark.sql.functions import col;F.when(col("col-1")>0.0) & (col("col-2")>0.0), 1).otherwise(0)


3
是否缺少一个 (F.when((col("col-1")>0.0) & (col("col-2")>0.0), 1).otherwise(0) - gannawag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接