如何在Spark 1.6 UDF中过滤可空的Array-Elements

时间:2017-02-26 08:26:15

标签: scala apache-spark apache-spark-sql

考虑以下DataFrame

root
 |-- values: array (nullable = true)
 |    |-- element: double (containsNull = true)

内容:

+-----------+
|     values|
+-----------+
|[1.0, null]|
+-----------+

现在我想将value列传递给UDF:

val inspect = udf((data:Seq[Double]) => {
  data.foreach(println)
  println()
  data.foreach(d => println(d))
  println()
  data.foreach(d => println(d==null))
  ""
})

df.withColumn("dummy",inspect($"values"))

我真的对上述println语句的输出感到困惑:

1.0
null

1.0
0.0

false
false

我的问题:

  1. 为什么foreach(println)没有提供与foreach(d=>println(d))相同的输出?
  2. 如果Double在第一个println语句中为null,我认为scala的Double不能为空?
  3. 如何在我的Seq其他han过滤0.0中过滤掉那些不安全的空值?我应该在UDF中使用Seq[java.lang.Double]作为输入的类型,然后过滤空值吗? (这有效,但我不确定这是否可行)
  4. 请注意,我知道this Question,但我的问题是针对数组类型的列。

1 个答案:

答案 0 :(得分:1)

  

为什么foreach(println)没有提供与foreach相同的输出(d => println(d))?

在期望Any的上下文中,完全跳过数据转换。这在If an Int can't be null, what does null.asInstanceOf[Int] mean?

中有详细解释
  

在第一个println语句中Double如何为null,我认为scala的Double不能为空?

内部二进制表示根本不使用Scala类型。解码数组数据后,它表示为Array[Any],元素被强制转换为简单asInstanceOf的声明类型。

  

我应该在UDF中使用Seq [java.lang.Double]作为输入的类型,然后过滤空值吗?

通常,如果值可以为空,那么您应该使用可以为空的外部类型或Option。不幸的是,只有第一个选项适用于UDF。