2017-07-24 54 views
1

我想寫一個火花UDF,用0.0代替雙字段的空值。我正在使用數據集API。這裏的UDF:火花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 

但是,當我以下列方式使用它星火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]) 

所以我在想,如果有火花的處理空Double值一些特殊的方法。

+0

這看起來像_DataFrame_ API,而不是_Dataset_ API - 「myDS」的類型是什麼? –

+0

它是一個大的案例類,其中「費率」字段的類型是雙倍。我通過執行sourceDF.as [MyCaseClass] –

+0

來初始化數據集。參閱相關問題https://issues.apache.org/jira/browse/SPARK-12648 - 允許UDF使用'Option [Double]'作爲可輸入的輸入的建議雙列(和其他基元) –

回答

2

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),後者表示從性能角度來看是有利的。

一般情況下,我建議你使用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]之前。