Spark DataFrame 转换为数据集不会更新架构中的 NullType 列

Spark DataFrame casting to Dataset Doesn't Update NullType Columns in Schema

我正在创建一个数据框,该数据框通过将某些列设置为空来进行初始化。在写出来之前,我将数据框输入为 case class A。鉴于我们有一个数据集 [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) 来解决,但这并不理想。是否有更好的解决方案来自动更新架构而无需手动转换列。

虽然实现您所寻找的确切目标是不切实际的,但我建议您

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

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

或者

  1. 使用像“shapeless”这样的反射API来使用与上面提到的类似的转换并使用你的(可配置的)案例class..