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 中,Int
是 AnyVal
的子类,而可空引用(在您编写的 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 2.0 中的 DataFrame 列创建数据集?