Spark弹性数据集之间的转换
基本转换小结
RDD -> DataFrame:
可以直接toDF 简单实现, 复杂结构是 构建RDD[Row] + StructType 实现
DataFrame -> RDD:
df.rdd 实现
DataFrame -> Dataset:
Dataset是强类型的DataFrame, 所以只需要 df.as[case class] 即可, 注意字段类型匹配
Dataset -> DataFrame:
df.toDF 即可
Dataset -> RDD:
DataFrame 使用 df.rdd 实现, 本身 DataFrame 是 Dataset[Row]
所以Dataset 也是 ds.rdd 实现转换
RDD -> Dataset:
Dataset 是强类型的所以这个地方要求RDD本身就存的是带有类型的数据(如RDD[case class]) ,使用rdd.toDS 即可完成转换.
试验代码
case class Person(name: String, age: Int)
object Convert {
def main(args: Array[String]): Unit = {
// 三种基本的弹性数据集合之间的转换.
val sparkConf: SparkConf = new SparkConf()
.setAppName("Type Convert")
.setMaster("local")
val sparkSession: SparkSession = SparkSession.builder()
.config(sparkConf).getOrCreate()
import sparkSession.implicits._
val sparkContext = sparkSession.sparkContext
//构建Rdd
val rdd1: RDD[Int] = sparkContext.makeRDD(List(1,2,3))
// 需要引入隐式变化 不然无法调用
print("RDD 2 DF")
// 没有指定列明的时候是value
val df1: DataFrame = rdd1.toDF("intvalue")
df1.printSchema()
df1.show()
print("df 2 rdd")
// df 2 rdd 结果是RDD[Row]
//val rdd2: RDD[Row] = df1.rdd
// 从RDD 到 DF 可以直接 使用Seq.toDF 得到
val df2: DataFrame = Seq(1,2,3).toDF("intvalue")
df2.printSchema()
df2.show()
//从 df 到 ds 需要提供强类型 使用as 转换 注意字段类型问题
// 如果df是从外部文件构建 整数 schema可能是bigint 所以需要将列转换一下类型. 和定义的样例类字段类型对应
// 复杂类型RDD到 df 之前其实是一列数据RDD到df 如果本身就是比较复杂的数据呢 需要使用 structType
val rdd3 = sparkContext.makeRDD(Seq(("a", 10), ("b", 20)))
.map(item => Row(item._1, item._2))
// 建立schema DF 需要
val dataSchema = StructType(List(StructField("name", StringType, nullable = true), StructField("age", IntegerType, nullable = true)))
// 复杂类型可能 rdd.toDF 无法实现 那么就老老实实 使用createDF + schema(StructType 和 StructField)实现
val df3: DataFrame = sparkSession.createDataFrame(rdd3, dataSchema)
print("内存中创建df 注意数值型 是 integer")
df3.printSchema()
df3.show()
print("DF 转换成 DS")
// DS 是强类型的 所以需要 as[定义样例类型] 完成转换.
val ds1: Dataset[Person] = df3.as[Person]
ds1.printSchema()
print("DS 转换回 DF")
val df4: DataFrame = ds1.toDF()
df4.printSchema()
print("DS 转回 RDD")
// 直接rdd 因为DS 是一般的 DataFrame 所以转回Rdd 直接.rdd
val rdd4: RDD[Person] = ds1.rdd
print("rdd 转 DS")
// 需要样例类型信息 而不是rdd 到DF 先构建Row Rdd 再添加 schema完成
val rdd5: RDD[Person] = sparkContext.makeRDD(Seq(Person("a", 10), Person("b", 20)))
val ds2: Dataset[Person] = rdd5.toDS()
ds2.printSchema()
sparkSession.close()
}
}