Spark:如果 DataFrame 有模式,DataFrame 如何成为 Dataset[Row]

Spark: How can DataFrame be Dataset[Row] if DataFrame's have a schema

This article claims that a DataFrame in Spark is equivalent to a Dataset[Row], but this blog post 表明 DataFrame 有一个架构。

以博客 post 中将 RDD 转换为 DataFrame 为例:如果 DataFrameDataset[Row] 相同,则将 RDDDataFrame 应该很简单

val rddToDF = rdd.map(value => Row(value))

但它显示的是这个

val rddStringToRowRDD = rdd.map(value => Row(value))
val dfschema = StructType(Array(StructField("value",StringType)))
val rddToDF = sparkSession.createDataFrame(rddStringToRowRDD,dfschema)
val rDDToDataSet = rddToDF.as[String]

显然,数据框实际上是行 和模式 的数据集。

在Spark 2.0中,代码中有: type DataFrame = Dataset[Row]

Dataset[Row],只是因为定义。

Dataset 也有架构,您可以使用 printSchema() 功能打印它。通常 Spark 会推断模式,因此您不必自己编写它 - 但它仍然存在 ;)

您还可以执行 createTempView(name) 并在 SQL 查询中使用它,就像 DataFrames 一样。

换句话说,Dataset = DataFrame from Spark 1.5 + encoder,即转换行给你的类。在 Spark 2.0 中合并类型后,DataFrame 只是 Dataset[Row] 的别名,因此没有指定编码器。

关于转换:rdd.map() 也 returns RDD,它从不 returns DataFrame。你可以这样做:

// Dataset[Row]=DataFrame, without encoder
val rddToDF = sparkSession.createDataFrame(rdd)
// And now it has information, that encoder for String should be used - so it becomes Dataset[String]
val rDDToDataSet = rddToDF.as[String]

// however, it can be shortened to:
val dataset = sparkSession.createDataset(rdd)

请注意(除了 T Gaweda 的答案之外)每个 Row (Row.schema) 都有一个关联的模式。但是,此架构在集成到 DataFrame(或 Dataset[Row]

之前不会设置
scala> Row(1).schema
res12: org.apache.spark.sql.types.StructType = null

scala> val rdd = sc.parallelize(List(Row(1)))
rdd: org.apache.spark.rdd.RDD[org.apache.spark.sql.Row] = ParallelCollectionRDD[5] at parallelize at <console>:28
scala> spark.createDataFrame(rdd,schema).first
res15: org.apache.spark.sql.Row = [1]
scala> spark.createDataFrame(rdd,schema).first.schema
res16: org.apache.spark.sql.types.StructType = StructType(StructField(a,IntegerType,true))