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)
来解决,但这并不理想。是否有更好的解决方案来自动更新架构而无需手动转换列。
虽然实现您所寻找的确切目标是不切实际的,但我建议您
- 生成字段名称到 DataType (spark) 映射的集合,例如
myTypes:Map[String, StructType]
并且您可以简单地转换为该类型 -
inputDS
.withColumn("filledLater", lit(null).cast(myTypes("filledLater")))
这样你就不必使用Dataset[T],而是使用Dataframe
或者
- 使用像“shapeless”这样的反射API来使用与上面提到的类似的转换并使用你的(可配置的)案例class..
我正在创建一个数据框,该数据框通过将某些列设置为空来进行初始化。在写出来之前,我将数据框输入为 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)
来解决,但这并不理想。是否有更好的解决方案来自动更新架构而无需手动转换列。
虽然实现您所寻找的确切目标是不切实际的,但我建议您
- 生成字段名称到 DataType (spark) 映射的集合,例如
myTypes:Map[String, StructType]
并且您可以简单地转换为该类型 -
inputDS
.withColumn("filledLater", lit(null).cast(myTypes("filledLater")))
这样你就不必使用Dataset[T],而是使用Dataframe
或者
- 使用像“shapeless”这样的反射API来使用与上面提到的类似的转换并使用你的(可配置的)案例class..