【问题标题】:Spark: RuntimeException: java.lang.String is not a valid external type for schema of dateSpark:RuntimeException:java.lang.String 不是日期模式的有效外部类型
【发布时间】:2020-12-16 19:05:42
【问题描述】:

这很好用:

import org.apache.spark.sql.types.{StructType, StructField, StringType, IntegerType, DateType}
import org.apache.spark.sql.functions._

val df = Seq( ("2018-01-01", "2018-01-31", 80)
            , ("2018-01-07","2018-01-10", 10)
            , ("2018-01-07","2018-01-31", 10)
            , ("2018-01-11","2018-01-31", 5)
            , ("2018-01-25","2018-01-27", 5)
            , ("2018-02-02","2018-02-23", 100)
            ).toDF("sd","ed","coins")

val schema = List(("sd", "date"), ("ed", "date"), ("coins", "integer"))
val newColumns = schema.map(c => col(c._1).cast(c._2))
val newDF = df.select(newColumns:_*)
newDF.show(false)

这是我提出的以下问题的解决方法:

import org.apache.spark.sql.types.{StructType, StructField, StringType, IntegerType, DateType};

val someData = Seq(
                     Row("2018-01-01","2018-01-31", 80)
                   , Row("2018-01-07","2018-01-10", 10)
                   , Row("2018-01-07","2018-01-31", 10)
                   , Row("2018-01-11","2018-01-31", 5)
                   , Row("2018-01-25","2018-01-27", 5)
                   , Row("2018-02-02","2018-02-23", 100)
                  )

val someSchema = List(
  StructField("sd", DateType, true),
  StructField("ed", DateType, true),
  StructField("coins", IntegerType, true),
)

val dfA = spark.createDataFrame(
  spark.sparkContext.parallelize(someData),
  StructType(someSchema)
)

dfA.show(false)

产生如下错误:

Caused by: RuntimeException: java.lang.String is not a valid external type for schema of date

我知道 int、bigint 问题,并在第一个 sn-p 中指出了日期的解决方法,但我似乎无法使用日期类型 - 我想知道第二个 sn-p 的方法,继续这条脉络。

【问题讨论】:

  • 很有趣...我想知道用例是什么?如果从 csv 读取,您可以指定日期格式/时间戳格式,并且大概这不应该发生......
  • 刚刚准备databricks考试和复习。我找不到正确的方法,诚然更具学术性,但人们希望这种方法可以理想地发挥作用
  • 也许我们只需要假设通常源始终来自磁盘,流并保留它,但我自己很好奇。

标签: scala apache-spark


【解决方案1】:

首先,您的日期是字符串,然后您将它们转换为带有newColumns 的日期。对于第二个实例,您试图将字符串值插入日期数据类型——它不起作用。它们首先需要是字符串(因为它们就是这样),然后将它们转换为一个日期,就像你在第一个实例中所做的那样。此外,您的结尾逗号是 someSchema ,我也没有看到 Row 正在导入。

【讨论】:

  • 观察多于答案。我得到了这一切,正在寻找优雅的方式。
  • 在笔记本中运行
  • 我试图告诉你幕后发生的事情。如果您查看执行计划,它完全相同。如果你想回答,就拿你所拥有的dfA.select(col("sd").cast('date'), col("ed").cast('date'), col('"coins"))。它不必是简洁的代码才能优雅。
  • 额外的,不会导致运行时问题,奇怪但就是这样
【解决方案2】:

经过大量实验,trying df.rdd.map{...asIntanceOf[Date],不喜勿喷。

如上所述,我的第一种方法是要走的路:

import org.apache.spark.sql.types.{StructType, StructField, StringType, IntegerType, DateType}
import org.apache.spark.sql.functions._

val df = Seq( ("2018-01-01", "2018-01-31", 80)
            , ("2018-01-07","2018-01-10", 10)
            , ("2018-01-07","2018-01-31", 10)
            , ("2018-01-11","2018-01-31", 5)
            , ("2018-01-25","2018-01-27", 5)
            , ("2018-02-02","2018-02-23", 100)
            ).toDF("sd","ed","coins")

val schema = List(("sd", "date"), ("ed", "date"), ("coins", "integer"))
val newColumns = schema.map(c => col(c._1).cast(c._2))
val newDF = df.select(newColumns:_*)
newDF.show(false)

【讨论】:

    猜你喜欢
    • 2021-11-29
    • 2022-08-16
    • 2021-07-23
    • 1970-01-01
    • 2018-09-19
    • 2018-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多