【问题标题】:Spark DataFrame casting to Dataset Doesn't Update NullType Columns in SchemaSpark DataFrame 转换为 Dataset 不会更新 Schema 中的 NullType 列
【发布时间】:2021-10-08 03:44:13
【问题描述】:

我正在创建一个数据框,该数据框被初始化为一些列设置为空。在写出之前,我将数据框键入为案例类 A。鉴于我们有一个 Dataset[A],我假设数据集的底层模式将具有正确的类型;但是,模式保留为 NullType。以下是如何重现的示例:

case class ExampleInput(
  name: String,
  age: Integer
)

case class ExampleOutput(
  name: String,
  age: Integer,
  filledLater: String
)

// Define Input
val inputDS: Dataset[ExampleInput] = Seq(ExampleInput("asdf", 1)).toDS

// Calculate Output
val outputDS: Dataset[ExampleOutput] = inputDS
  .withColumn("filledLater", lit(null))
  .as[ExampleOutput]

预期结果架构:

StructType(
  StructField("name", StringType, true),
  StructField("age", StringType, false),
  StructField("filledLater", StringType, true)
)

观察结果架构:

StructType(
  StructField("name", StringType, true),
  StructField("age", StringType, false),
  StructField("filledLater", NullType, true)
)

这可以通过使用.map(x => x: ExampleOutput) 来解决,但这不太理想。有没有更好的解决方案来自动更新架构而无需手动转换列。

【问题讨论】:

    标签: scala apache-spark apache-spark-sql apache-spark-dataset


    【解决方案1】:

    虽然实现您正在寻找的确切东西是不切实际的,但我建议您要么

    1. 生成字段名称到 DataType (spark) 映射的集合,例如myTypes:Map[String, StructType] 并且您可以简单地转换为该类型 -
    inputDS
      .withColumn("filledLater", lit(null).cast(myTypes("filledLater")))
    

    这样就不必使用Dataset[T],而是使用Dataframe

    或者

    1. 使用“shapeless”之类的反射 API 来使用与上述类似的转换并使用您的(可配置的)案例类。

    【讨论】:

    • 是的,我最终在我们当前的解决方案中使用了地图,不确定是否有更好的解决方案。我会将其标记为已接受!谢谢!
    猜你喜欢
    • 2017-04-03
    • 2017-04-17
    • 2017-06-21
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-09
    • 2020-08-10
    相关资源
    最近更新 更多