如何处理PRAPS UDF输入/原始可定性类型的输出



问题:

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

相应地向文档:

请注意,如果您使用原始参数,则无法检查 是否为空 原始输入为零。如果您想这样做,请使用盒装类型或[[option]] 零处理自己。


因此,最简单的解决方案只是使用盒装类型如果您的UDF输入是原始类型的无效列或/和/您需要从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|
+-----+-----+

我也将使用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()

基于SparkSQL上提供的解决方案:如何处理用户定义的函数中的空值?由 @Zero323,实现请求结果的另一种方法是:

import scala.util.Try
val udfHandlingNulls udf((x: Double) => Try(2.0).toOption)
inputDF.withColumn("y", udfHandlingNulls($"x")).show()

相关内容

  • 没有找到相关文章

最新更新