Spark DataFrame 空值到数据集

Posted

技术标签:

【中文标题】Spark DataFrame 空值到数据集【英文标题】:Spark DataFrame nulls to Dataset 【发布时间】:2017-03-31 00:03:42 【问题描述】:

从 MS SQL 数据库导入数据时,可能会出现空值。在 Spark 中,DataFrames 能够处理空值。但是当我尝试将 DataFrame 转换为强类型数据集时,我收到了编码器错误。

这是一个简单的例子:

case class optionTest(var a: Option[Int], var b: Option[Int])

object testObject 
  def main(args: Array[String]): Unit = 
    import spark.implicits._
    val df = spark.sparkContext.parallelize(Seq(input)).toDF()

    val df2 = Seq((1, 3), (3, Option(null)))
                 .toDF("a", "b")
                 .as[optionTest]

    df2.show()
  

这里是这个案例的错误:

No Encoder found for Any
- field (class: "java.lang.Object", name: "_2")
- root class: "scala.Tuple2"
java.lang.UnsupportedOperationException: No Encoder found for Any
- field (class: "java.lang.Object", name: "_2")
- root class: "scala.Tuple2"

在从 DataFrame 创建数据集时,推荐的处理可为空值的方法是什么?

【问题讨论】:

【参考方案1】:

问题是您的 Dataframe 与您的案例类不匹配。

您的第一对是(Int, Int),第二对是(Int, Option[Null])

需要注意的是,如果您要表示 Option[Int],则该值将是 Some(3),例如,或 None 表示不存在的值。

需要注意的一点是,在 Scala 中,IntAnyVal 的子类,而可空引用(在您编写的 Scala 代码中应该几乎不存在)位于 Scala 对象层次结构的 AnyRef 一侧.

因为您有一堆对象遍布 Scala 对象模型,Spark 必须将您的数据视为 Any,一切的超类。没有编码器可以处理。

综上所述,您的数据必须如下所示:

val df2 = Seq((Some(1), Some(3)), (Some(3), None))

附带说明一下,您的案例类应如下所示:

case class OptionTest(a: Option[Int], b: Option[Int])

【讨论】:

这很有帮助,但是当转到数据集时,您将如何处理 DataFrame 中的空值? 有趣的是你应该问。我之前answered a similar question。【参考方案2】:

如果您想使用Option,您必须将它用于所有记录。您还应该使用None 而不是Option(null)

Seq((1, Some(3)), (3, None)).toDF("a", "b").as[optionTest]

【讨论】:

以上是关于Spark DataFrame 空值到数据集的主要内容,如果未能解决你的问题,请参考以下文章

Spark 数据集相对于 DataFrame 的缺点

如何从 Spark 2.0 中的 DataFrame 列创建数据集?

如何从 RDD 创建 Spark 数据集

spark DataFrame 常见操作

学习笔记Spark—— Spark SQL应用—— Spark DataFrame基础操作

spark dataframe操作集锦(提取前几行,合并,入库等)