Spark UDF 不适用于 Double 字段中的空值
Spark UDF not working with null values in Double field
我正在尝试编写一个 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)
其中任何一个都允许您使用静态类型的 API(不是 SQL / DataFrame
)处理 nulls
,从性能的角度来看,后一种表示是有利的.
一般来说,我建议使用 SQL API:
来填充 NULLs
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]
之前。
我正在尝试编写一个 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)
其中任何一个都允许您使用静态类型的 API(不是 SQL / DataFrame
)处理 nulls
,从性能的角度来看,后一种表示是有利的.
一般来说,我建议使用 SQL API:
来填充NULLs
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]
之前。