将DataFrame映射到案例类时,为什么Some(null)转换为None

时间:2018-08-21 15:50:50

标签: scala apache-spark

在REPL中,为案例类构造函数提供Some(null)参数不会引起任何意外,该值将保留并分配给案例类的字段:

scala> case class CaseClassWithOptionField(opt:Option[String])
defined class CaseClassWithOptionField

scala> CaseClassWithOptionField(Some(null))
res0: CaseClassWithOptionField = CaseClassWithOptionField(Some(null))

但是,当我将DataFrame映射到字段类型为Option[T]的案例类时,Some(null)变成了None :(我在Jupyter笔记本中运行了此事)

import sparkSession.implicits._

val someDF = Seq(
  (8, Some(null.asInstanceOf[String])),
  (64, Some(null.asInstanceOf[String])),
  (-27, Some(null.asInstanceOf[String]))
).toDF("id", "opt")

case class CCWithOpt(id: Int, opt: Option[String])

someDF.as[CCWithOpt] take 1 // gives [CCWithOpt(8,None)]

为什么会这样?

1 个答案:

答案 0 :(得分:2)

Spark将DataFrame中的Option[T]类型的列解释为类型nullable的{​​{1}}列。例如:

T

请注意,在val df = Seq( (1, Some("a"), Some(1)), (2, Some(null), Some(2)), (3, Some("c"), Some(3)), (4, None, None) ).toDF("c1", "c2", "c3") df.show // +---+----+----+ // | c1| c2| c3| // +---+----+----+ // | 1| a| 1| // | 2|null| 2| // | 3| c| 3| // | 4|null|null| // +---+----+----+ df.printSchema // root // |-- c1: integer (nullable = false) // |-- c2: string (nullable = true) // |-- c3: integer (nullable = true) 列中,c2Some(null)相同。

对于您的None DataFrame,Spark推断someDF列为opt的{​​{1}}列,并将nullable视为String。转换为Some(null.asInstanceOf[String])后,null将恢复为Dataset[CCWithOpt]