scala - Spark UDF 不适用于 Double 字段中的空值

标签 scala apache-spark apache-spark-dataset

我正在尝试编写一个 spark UDF,用 0.0 替换 Double 字段的空值。我正在使用数据集 API。这是UDF:

val coalesceToZero=udf((rate: Double) =>  if(Option(rate).isDefined) rate else 0.0)

这是基于我测试可以正常工作的以下功能:
def cz(value: Double): Double = if(Option(value).isDefined) value else 0.0

cz(null.asInstanceOf[Double])
cz: (value: Double)Double
res15: Double = 0.0

但是当我以下列方式在 Spark 中使用它时,UDF 不起作用。
myDS.filter($"rate".isNull)
    .select($"rate", coalesceToZero($"rate")).show

+----+---------+
|rate|UDF(rate)|
+----+---------+
|null|     null|
|null|     null|
|null|     null|
|null|     null|
|null|     null|
|null|     null|
+----+---------+

但是,以下工作:
val coalesceToZero=udf((rate: Any) =>  if(rate == null) 0.0 else rate.asInstanceOf[Double])

所以我想知道 Spark 是否有一些特殊的方式来处理 null Double 值。

最佳答案

scala.Double不能是 null和您使用的功能,似乎只是因为:

scala> null.asInstanceOf[Double]
res2: Double = 0.0

(您可以在 If an Int can't be null, what does null.asInstanceOf[Int] mean? 中找到描述此行为的极好答案)。

myDS是静态类型的数据集,正确的方法是使用 Option[Double] :
case class MyCaseClass(rate: Option[Double])

java.lang.Double :
case class MyCaseClass(rate: java.lang.Double)

这些中的任何一个都可以让您处理 nulls使用静态类型的 API(不是 SQL/DataFrame),从性能角度来看,后一种表示是有利的。

一般来说,我建议填写 NULLs使用 SQL API:
import org.apache.spark.sql.functions.{coalesce, lit}

myDS.withColumn("rate", coalesce($"rate", lit(0.0)))

DataFrameNaFunctions.fill :
df.na.fill(0.0, Seq("rate"))

转换前 Dataset[Row]Dataset[MyCaseClass] .

关于scala - Spark UDF 不适用于 Double 字段中的空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45285253/

相关文章:

function - 如何调用从另一个函数返回的函数?

scala - 具有多个表的光滑外连接

scala - Spark数据帧-按键减少

scala - 对象 apache 不是包 org 的成员

scala - 在不关闭系统本身的情况下停止系统中的所有参与者?

python - 如何在 python 中使用 `map` 将 dict 值转换为整数?

apache-spark - 相当于 Scala Dataset#transform 方法的 Pyspark 变换方法

java.lang.RuntimeException : Error while encoding: java. lang.ArrayIndexOutOfBoundsException:1

apache-spark - 启动 Spark History Server 时如何指定 Spark 属性?

apache-spark - 将 Hive Sql 转换为 Spark Sql