问题:
1)如果输入是包含null
的基本类型的列,则Spark不会调用UDF:
inputDF.show()
+-----+
| x |
+-----+
| null|
| 1.0|
+-----+
inputDF
.withColumn("y",
udf { (x: Double) => 2.0 }.apply($"x") // will not be invoked if $"x" == null
)
.show()
+-----+-----+
| x | y |
+-----+-----+
| null| null|
| 1.0| 2.0|
+-----+-----+
2)无法从UDF中将null
作为基本类型列生成:
udf { (x: String) => null: Double } // compile error
答案 0 :(得分:6)
相应于the docs:
请注意,如果使用原始参数,则无法检查 如果它为null,则UDF将为您返回null 原始输入为空。 如果您愿意,请使用盒装类型或[[选项]] 自我处理。
因此,最简单的解决方案就是使用
如果您的UDF输入是基本类型的可空列,则为盒装类型
OR / AND您需要从UDF输出null作为基本类型的列:
inputDF
.withColumn("y",
udf { (x: java.lang.Double) =>
(if (x == null) 1 else null): java.lang.Integer
}.apply($"x")
)
.show()
+-----+-----+
| x | y |
+-----+-----+
| null| null|
| 1.0| 2.0|
+-----+-----+
答案 1 :(得分:2)
我也会使用Artur的解决方案,但是使用struct
还有另一种不使用javas包装类的方法:
import org.apache.spark.sql.functions.struct
import org.apache.spark.sql.Row
inputDF
.withColumn("y",
udf { (r: Row) =>
if (r.isNullAt(0)) Some(1) else None
}.apply(struct($"x"))
)
.show()
答案 2 :(得分:0)
根据SparkSQL: How to deal with null values in user defined function?在@zero323提供的解决方案,获得请求结果的另一种方法是:
import scala.util.Try
val udfHandlingNulls udf((x: Double) => Try(2.0).toOption)
inputDF.withColumn("y", udfHandlingNulls($"x")).show()