Spark DataFrame是无类型的,而DatFrame有模式吗?

时间:2018-09-12 06:02:07

标签: apache-spark apache-spark-sql bigdata

我是Spark的初学者,在阅读有关Dataframe的信息时,我经常发现以下两个关于dataframe的语句- 1)DataFrame是无类型的 2)DataFrame具有架构(就像数据库表一样,它具有与表属性有关的所有信息-名称,类型,而不是null)

两个陈述都不矛盾吗?首先我们说的是未输入数据框,同时我们也说的是数据框具有有关所有列的信息,即模式,请帮助我我在这里缺少的内容吗?因为如果数据框具有模式,那么它也知道列的类型,那么它如何变为非类型?

1 个答案:

答案 0 :(得分:1)

DataFrame是动态类型的,而Dataset和RDD是静态类型的。这意味着在定义数据集或RDD时,您需要显式指定一个表示内容的类。这很有用,因为当您在数据集上编写转换时,编译器可以检查代码的类型安全性。以这个宠物信息数据集为例。当我使用pet.speciespet.name时,编译器会在编译时知道它们的类型。

case class Pet(name: String, species: String, age: Int, weight: Double)

val data: Dataset[Pet] = Seq(
  Pet("spot", "dog", 2, 50.5),
  Pet("mittens", "cat", 11, 15.5),
  Pet("mickey", "mouse", 1, 1.5)).toDS
println(data.map(x => x.getClass.getSimpleName).first)
// Pet

val newDataset: Dataset[String] = data.map(pet => s"I have a ${pet.species} named ${pet.name}.")

当我们切换到使用DataFrame时,架构保持不变,并且数据仍被键入(或结构化),但是此信息仅在运行时可用。这称为动态类型。这可以防止编译器发现错误,但是它非常有用,因为它允许您编写类似sql的语句并动态定义新列,例如,将列追加到现有DataFrame中,而无需为每个类定义新类。一点操作。缺点是您可以定义错误的操作,这些操作会导致null或在某些情况下导致运行时错误。

val df: DataFrame = data.toDF
df.printSchema()
// root
// |-- name: string (nullable = true)
// |-- species: string (nullable = true)
// |-- age: integer (nullable = false)
// |-- weight: double (nullable = false)

val newDf: DataFrame = df
  .withColumn("some column", ($"age" + $"weight"))
  .withColumn("bad column", ($"name" + $"age"))
newDf.show()
// +-------+-------+---+------+-----------+----------+
// |   name|species|age|weight|some column|bad column|
// +-------+-------+---+------+-----------+----------+
// |   spot|    dog|  2|  50.5|       52.5|      null|
// |mittens|    cat| 11|  15.5|       26.5|      null|
// | mickey|  mouse|  1|   1.5|        2.5|      null|
// +-------+-------+---+------+-----------+----------+