[英]How to use Option with Spark UDF
我有一个像这样的数据集:
+----+------+
|code|status|
+-----------+
| 1| "new"|
| 2| null|
| 3| null|
+----+------+
我想写一个依赖于两列的UDF。
我按照此答案中的第二种方法来工作,该方法是在UDF外部处理null
,并编写myFn
以将Boolean作为第二个参数:
df.withColumn("new_column",
when(pst_regs("status").isNull,
myFnUdf($"code", lit(false))
)
.otherwise(
myFnUdf($"code", lit(true))
)
)
为了处理UDF中的null,我在此答案中介绍了一种方法,该方法涉及“用Options
包裹参数”。 我试过这样的代码:
df.withColumn("new_column", myFnUdf($"code", $"status"))
def myFn(code: Int, status: String) = (code, Option(status)) match {
case (1, "new") => "1_with_new_status"
case (2, Some(_)) => "2_with_any_status"
case (3, None) => "3_no_status"
}
但是具有null
的行给出type mismatch; found :None.type required String
type mismatch; found :None.type required String
。 我还尝试在udf创建期间用Option
包裹一个参数,但没有成功。 其基本形式(不带选件)如下所示:
myFnUdf = udf[String, Int, String](myFn(_:Int, _:String))
我是Scala的新手,所以我确定我缺少一些简单的东西。 我困惑的部分原因可能是从函数创建udf的语法不同(例如,按照https://jaceklaskowski.gitbooks.io/mastering-apache-spark/content/spark-sql-udfs.html ),所以我不确定我正在使用最好的方法。 任何帮助表示赞赏!
编辑
编辑以根据@ user6910411和@sgvd注释添加缺少的(1, "new")
大小写。
首先,您正在使用的某些代码可能在这里丢失了。 当我尝试将示例myFn
转换为val myFnUdf = udf(myFn _)
的UDF并使用df.withColumn("new_column", myFnUdf($"code", $"status")).show
,我不知道不会得到类型不匹配,而是出现MatchError
,如user6910411所述。 这是因为没有要匹配的模式(1, "new")
。
除此之外,尽管通常最好使用Scala的Options而不是原始的null
值,但在这种情况下您不必这样做。 以下示例直接使用null
:
val my_udf = udf((code: Int, status: String) => status match {
case null => "no status"
case _ => "with status"
})
df.withColumn("new_column", my_udf($"code", $"status")).show
结果:
+----+------+-----------+
|code|status| new_column|
+----+------+-----------+
| 1| new|with status|
| 2| null| no status|
| 2| null| no status|
+----+------+-----------+
用选项包装仍然有效:
val my_udf = udf((code: Int, status: String) => Option(status) match {
case None => "no status"
case Some(_) => "with status"
})
这给出了相同的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.