使用 UDF Spark 将嵌套数组字符串类型转换为嵌套数组日期类型



Input

f1 : [["2017-08-08","2017/08/08"],["2017-08-08","2017/08/08"]]

F1 的架构:ArrayType(ArrayType(StringType))

我想使用火花 UDF 将日期值从字符串转换为日期格式。 这里的输入可能有Array[Any]。我写了 udf,它适用于像["2017-08-07","2013/08/02"]这样的一维值。对于一维,我的 udf 将是:

def toDateFormatUdf(dateFormat:String) = udf(( dateValue: mutable.WrappedArray[_]) =>  dateValue match{
case null => null
case datevalue: mutable.WrappedArray[String] => datevalue.map(date => new java.sql.Date(new SimpleDateFormat(dateFormat).parse(String.valueOf(date)).getTime))
})

我尝试使用Seq[Row]类型作为UDF参数,但无法形成逻辑。有没有办法为 Scala 中的多维数组实现 UDF?

如果数据具有一致的格式,您可以cast,但在这里它将排除yyyy/MM/dd记录:

val df = Seq((1L, Seq(Seq("2017-08-08", "2017/08/08"), Seq("2017-08-08","2017/08/08")))).toDF("id", "dates")
df.select($"dates".cast("array<array<date>>")).show(1, false)
+----------------------------------------------------------------+
|dates                                                           |
+----------------------------------------------------------------+
|[WrappedArray(2017-08-08, null), WrappedArray(2017-08-08, null)]|
+----------------------------------------------------------------+

在这里,我只会重写格式:

val f1 = "(^[0-9]{4})-([0-9]{2})-([0-9]{2})$".r
val f2 = "(^[0-9]{4})/([0-9]{2})/([0-9]{2})$".r
val reformat = udf((xxs: Seq[Seq[String]]) => xxs match {
case null => null
case xxs => xxs.map {
case null => null
case xs => xs.map { x=> {
x match {
case null => null
case f1(_, _, _) => x
case f2(year, month, day) => s"${year}-${month}-${day}"
case _ => null
}
}}
}
})

和演员

df.select(reformat($"dates")).show(1, false)
+----------------------------------------------------------------------------+
|UDF(dates)                                                                  |
+----------------------------------------------------------------------------+
|[WrappedArray(2017-08-08, 2017-08-08), WrappedArray(2017-08-08, 2017-08-08)]|
+----------------------------------------------------------------------------+

以避免不必要的SimpleDateFormat初始化。

最新更新