You need to enable JavaScript to run this app. Spark DataFrame添加枚举类型列及转含枚举的样例类列表方法咨询
优惠活动
大模型
产品
解决方案
定价
更多

Spark DataFrame添加枚举类型列及转含枚举的样例类列表方法咨询

注意:Test样例类的属性名type是Scala保留关键字,定义时需要用反引号包裹,否则会触发语法错误,样例类参考定义如下:

object SaleType extends Enumeration {
  val SALE, PURCHASE = Value
}
case class Test(id: Int, name: String, `type`: SaleType.Value)

方案1:收集后手动映射(实现最简单,适配小数据量场景)

不需要提前在DataFrame中新增枚举类型列,直接收集原始DataFrame的Row数据,遍历过程中根据业务规则赋值枚举即可,完全规避Spark DataFrame不支持自定义枚举作为列类型的问题:

import org.apache.spark.sql.functions._

val df = Seq(
  (0, "p"),
  (1, "s")
).toDF("id", "name")

val result: List[Test] = df.collect().map { row =>
  val id = row.getAs[Int]("id")
  val name = row.getAs[String]("name")
  val saleType = if (name == "p") SaleType.PURCHASE else SaleType.SALE
  Test(id, name, saleType)
}.toList

如果你的业务逻辑已经提前生成了存储枚举名称的字符串列,也可以用withName方法直接映射枚举:

val dfWithStrType = df.withColumn("type_str", when(col("name") === "p", "PURCHASE").otherwise("SALE"))
val result: List[Test] = dfWithStrType.collect().map { row =>
  Test(
    row.getAs[Int]("id"),
    row.getAs[String]("name"),
    SaleType.withName(row.getAs[String]("type_str"))
  )
}.toList

方案2:自定义Encoder实现Dataset直接转换(适配大数据量场景)

如果后续还需要对Test类型的数据集做算子操作、不想提前collect到驱动端,可以显式为Test类定义Kryo编码器,在Dataset层面完成类型转换:

import org.apache.spark.sql.Encoders

implicit val testEncoder = Encoders.kryo[Test]

val testDs = df.map { row =>
  val id = row.getAs[Int]("id")
  val name = row.getAs[String]("name")
  val saleType = if (name == "p") SaleType.PURCHASE else SaleType.SALE
  Test(id, name, saleType)
}
// 需要时再collect转List
val result: List[Test] = testDs.collect().toList

内容的提问来源于stack exchange,提问作者Henri Thorpe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 02:54:05