【问题标题】:spark udf with data frame带有数据框的火花 udf
【发布时间】:2016-04-21 21:57:25
【问题描述】:

我使用的是 Spark 1.3。我有一个数据集,其中列(ordering_date 列)中的日期为 yyyy/MM/dd 格式。我想对日期进行一些计算,因此我想使用 jodatime 进行一些转换/格式化。这是我拥有的 udf:

 val return_date = udf((str: String, dtf: DateTimeFormatter) => dtf.formatted(str))

这是调用 udf 的代码。但是,我收到“不适用”的错误消息。我需要注册这个 UDF 还是我在这里遗漏了什么?

val user_with_dates_formatted = users.withColumn(
  "formatted_date",
  return_date(users("ordering_date"), DateTimeFormat.forPattern("yyyy/MM/dd")
)

【问题讨论】:

    标签: apache-spark apache-spark-sql


    【解决方案1】:

    我不相信您可以将DateTimeFormatter 作为参数传递给UDF。您只能传入Column。一种解决方案是:

    val return_date = udf((str: String, format: String) => {
      DateTimeFormat.forPatten(format).formatted(str))
    })
    

    然后:

    val user_with_dates_formatted = users.withColumn(
      "formatted_date",
      return_date(users("ordering_date"), lit("yyyy/MM/dd"))
    )
    

    不过,老实说——这和你原来的算法都有同样的问题。他们都使用forPattern 解析yyyy/MM/dd 来处理每条记录。最好是创建一个包裹在Map[String,DateTimeFormatter] 周围的单例对象,可能像这样(完全未经测试,但你明白了):

    object DateFormatters {
      var formatters = Map[String,DateTimeFormatter]()
    
      def getFormatter(format: String) : DateTimeFormatter = {
        if (formatters.get(format).isEmpty) {
          formatters = formatters + (format -> DateTimeFormat.forPattern(format))
        }
        formatters.get(format).get
      }
    }
    

    然后您将UDF 更改为:

    val return_date = udf((str: String, format: String) => {
      DateFormatters.getFormatter(format).formatted(str))
    })
    

    这样,DateTimeFormat.forPattern(...) 每个执行程序的每个格式只调用一次。

    关于单例对象解决方案需要注意的一点是,您不能在 spark-shell 中定义对象——您必须将其打包到 JAR 文件中并使用 --jars 选项到 spark-shell 如果你想在 shell 中使用 DateFormatters 对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-01
      • 2020-04-20
      相关资源
      最近更新 更多