Spark UDF 类型不匹配错误
Posted
技术标签:
【中文标题】Spark UDF 类型不匹配错误【英文标题】:Spark UDF type mismatch error 【发布时间】:2017-03-07 21:38:06 【问题描述】:我正在尝试编写一个 UDF 来将时间戳转换为表示一周中的小时的整数。我可以像这样使用 SparkSql 轻松完成此操作。
我的代码中有许多 UDF 使用这种精确的语法,但这个正在尝试类型不匹配错误。我还尝试使用col("session_ts_start")
调用我的UDF,但这也失败了。
import spark.implicits._
import java.sql.Timestamp
import org.apache.spark.sql.functions._
def getHourOfWeek() = udf(
(ts: Timestamp) => unix_timestamp(ts)
)
val dDF = df.withColumn("hour", getHourOfWeek()(df("session_ts_start")))
dDF.show()
<console>:154: error: type mismatch;
found : java.sql.Timestamp
required: org.apache.spark.sql.Column
(ts: Timestamp) => unix_timestamp(ts)
【问题讨论】:
【参考方案1】:unix_timestamp
是一个 SQL 函数。它operates on Columns
不是外部值:
def unix_timestamp(s: Column): Column
它不能在 UDF 中使用。
我正在尝试 (...) 将时间戳转换为表示星期几的整数
import org.apache.spark.sql.Column
import org.apache.spark.sql.functions.date_format, hour
def getHourOfWeek(c: Column) =
// https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
(date_format(c, "u").cast("integer") - 1) * 24 + hour(c)
val df = Seq("2017-03-07 01:00:00").toDF("ts").select($"ts".cast("timestamp"))
df.select(getHourOfWeek($"ts").alias("hour")).show
+----+
|hour|
+----+
| 25|
+----+
另一种可能的解决方案:
import org.apache.spark.sql.functions.next_day, date_sub
def getHourOfWeek2(c: Column) = ((
c.cast("bigint") -
date_sub(next_day(c, "Mon"), 7).cast("timestamp").cast("bigint")
) / 3600).cast("int")
df.select(getHourOfWeek2($"ts").alias("hour"))
+----+
|hour|
+----+
| 25|
+----+
注意:两种解决方案都不能处理夏令时或其他日期/时间细节。
【讨论】:
以上是关于Spark UDF 类型不匹配错误的主要内容,如果未能解决你的问题,请参考以下文章
Presto 或 Trino 自定义 UDF 得到“不匹配预期的 Java 类型错误”
在 Spark SQL 中使用 UDF 函数后,如何修复这种类型的错误?
Spark - aggregateByKey 类型不匹配错误
在 spark 数据框中运行 UDF 时,不支持获取 org.apache.spark.sql.Column 类型的架构