以下是我用于使用少量列计算值的Spark UDF。
def spark_udf_func(s: String, i:Int): Boolean = {
// I'm returning true regardless of the parameters passed to it.
true
}
val spark_udf = org.apache.spark.sql.functions.udf(spark_udf_func _)
val df = sc.parallelize(Array[(Option[String], Option[Int])](
(Some("Rafferty"), Some(31)),
(null, Some(33)),
(Some("Heisenberg"), Some(33)),
(Some("Williams"), null)
)).toDF("LastName", "DepartmentID")
df.withColumn("valid", spark_udf(df.col("LastName"), df.col("DepartmentID"))).show()
+----------+------------+-----+
| LastName|DepartmentID|valid|
+----------+------------+-----+
| Rafferty| 31| true|
| null| 33| true|
|Heisenberg| 33| true|
| Williams| null| null|
+----------+------------+-----+
任何人都可以解释为什么有效列的值对于最后一行为空?
当我检查了火花计划时,我能够发现计划有一个案例条件,它说如果column2(DepartmentID)为null,则必须返回null。
== Physical Plan ==
*Project [_1#699 AS LastName#702, _2#700 AS DepartmentID#703, if (isnull(_2#700)) null else UDF(_1#699, _2#700) AS valid#717]
+- *SerializeFromObject [staticinvoke(class org.apache.spark.unsafe.types.UTF8String, StringType, fromString, unwrapoption(ObjectType(class java.lang.String), assertnotnull(input[0, scala.Tuple2, true])._1), true) AS _1#699, unwrapoption(IntegerType, assertnotnull(input[0, scala.Tuple2, true])._2) AS _2#700]
+- Scan ExternalRDDScan[obj#698]
为什么我们在Spark中有这样的行为?
为什么只有Integer列?
我在这里做错了什么,当UDF参数为null时,在UDF中处理null的正确方法是什么?
答案 0 :(得分:6)
问题是null不是scala Int的有效值(它是支持值),而它是String的有效值。 Int等同于java int原语,并且必须具有值。这意味着当值为null时无法调用udf,因此仍为null。
有两种方法可以解决这个问题:
可以找到here
的一个很好的解释答案 1 :(得分:0)
要接受null,请使用Integer(Java数据类型而不是Scala Int)
def spark_udf_func(s: String, i:Integer): Boolean = {
// I'm returning true regardless of the parameters passed to it.
if(i == null) false else true
}