[英]Scala and Spark UDF function
我做了一個簡單的UDF來轉換或從spark中的temptabl中的時間字段中提取一些值。 我注冊了該函數,但是當我使用sql調用該函數時,它會拋出一個NullPointerException。 以下是我的功能和執行過程。 我正在使用Zeppelin。 扼殺這是昨天工作,但它今天早上停止工作。
功能
def convert( time:String ) : String = {
val sdf = new java.text.SimpleDateFormat("HH:mm")
val time1 = sdf.parse(time)
return sdf.format(time1)
}
注冊功能
sqlContext.udf.register("convert",convert _)
沒有SQL測試函數 - 這是有效的
convert(12:12:12) -> returns 12:12
在Zeppelin這個FAILS中用SQL測試函數。
%sql
select convert(time) from temptable limit 10
結構的誘惑力
root
|-- date: string (nullable = true)
|-- time: string (nullable = true)
|-- serverip: string (nullable = true)
|-- request: string (nullable = true)
|-- resource: string (nullable = true)
|-- protocol: integer (nullable = true)
|-- sourceip: string (nullable = true)
我得到的堆棧跟蹤的一部分。
java.lang.NullPointerException
at org.apache.hadoop.hive.ql.exec.FunctionRegistry.getFunctionInfo(FunctionRegistry.java:643)
at org.apache.hadoop.hive.ql.exec.FunctionRegistry.getFunctionInfo(FunctionRegistry.java:652)
at org.apache.spark.sql.hive.HiveFunctionRegistry.lookupFunction(hiveUdfs.scala:54)
at org.apache.spark.sql.hive.HiveContext$$anon$3.org$apache$spark$sql$catalyst$analysis$OverrideFunctionRegistry$$super$lookupFunction(HiveContext.scala:376)
at org.apache.spark.sql.catalyst.analysis.OverrideFunctionRegistry$$anonfun$lookupFunction$2.apply(FunctionRegistry.scala:44)
at org.apache.spark.sql.catalyst.analysis.OverrideFunctionRegistry$$anonfun$lookupFunction$2.apply(FunctionRegistry.scala:44)
at scala.Option.getOrElse(Option.scala:120)
at org.apache.spark.sql.catalyst.analysis.OverrideFunctionRegistry$class.lookupFunction(FunctionRegistry.scala:44)
使用udf而不是直接定義函數
import org.apache.spark.sql.functions._
val convert = udf[String, String](time => {
val sdf = new java.text.SimpleDateFormat("HH:mm")
val time1 = sdf.parse(time)
sdf.format(time1)
}
)
udf的輸入參數是Column(或Columns)。 返回類型是Column。
case class UserDefinedFunction protected[sql] (
f: AnyRef,
dataType: DataType,
inputTypes: Option[Seq[DataType]]) {
def apply(exprs: Column*): Column = {
Column(ScalaUDF(f, dataType, exprs.map(_.expr), inputTypes.getOrElse(Nil)))
}
}
您必須將您的函數定義為UDF。
import org.apache.spark.sql.expressions.UserDefinedFunction
import org.apache.spark.sql.functions.udf
val convertUDF: UserDefinedFunction = udf((time:String) => {
val sdf = new java.text.SimpleDateFormat("HH:mm")
val time1 = sdf.parse(time)
sdf.format(time1)
})
接下來,您將在您的DataFrame上應用UDF。
// assuming your DataFrame is already defined
dataFrame.withColumn("time", convertUDF(col("time"))) // using the same name replaces existing
現在,關於您的實際問題,您收到此錯誤的一個原因可能是因為您的DataFrame包含空值的行。 如果在應用UDF之前將其過濾掉,則應該能夠繼續沒有問題。
dataFrame.filter(col("time").isNotNull)
我很好奇當運行UDF而不是遇到null時,還有什么導致NullPointerException,如果你找到了與我的建議不同的原因,我很高興知道。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.