【问题标题】:Converting nested ArrayType of String to Nested ArrayType of date using UDF spark使用 UDF spark 将嵌套的字符串 ArrayType 转换为日期的嵌套 ArrayType
【发布时间】:2017-08-28 19:44:08
【问题描述】:

输入

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

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

我想使用 spark UDF 将日期值从字符串转换为日期格式。 这里输入可能有Array[Any]。我写过适用于像["2017-08-07","2013/08/02"] 这样的单维值的udf。对于单维我的 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?

【问题讨论】:

    标签: scala apache-spark multidimensional-array nested user-defined-functions


    【解决方案1】:

    如果数据格式一致,您可以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初始化。

    【讨论】:

    • 是否可以制作一个通用的 UDF 来支持任何维度的字符串输入数组?
    • 我无法找到通用 UDF 的解决方案。那么为每个维度编写不同的 UDF 是个好主意吗?对于 1D 数组,我的 udf 参数将是 Seq[String],对于 2D 数组,它将是 Seq[Seq[String]],对于 3D、4D 也是如此......
    猜你喜欢
    • 1970-01-01
    • 2017-08-05
    • 1970-01-01
    • 2016-02-08
    • 2020-05-04
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    • 2020-10-02
    相关资源
    最近更新 更多