Spark基础-RDD、DataFrame、DataSet转换方式以及异同

文章目录

    • 1. RDD转换成DataFrame的两种方式
    • 2.DataSet的创建
    • 3.类型之间的转换总结
    • 4.RDD、DataFrame、DataSet三者的共性与区别
      • 共性:
      • 区别:
        • RDD:
        • DataFrame:
        • Dataset:

1. RDD转换成DataFrame的两种方式

rdd可以通过下面这种方式得到DataFrame:

valpeopleDF = peopleRdd.map(_.split("")).filter(_.length==2).map(paras=>
(paras(0),paras(1).trim().toInt)).toDF("name", "age")

我们在toDF方法里,指定DataFrame的信息。
我们也可以通过下面的方式,把RDD转换为DataFrame
SparkSQL能够自动将包含有case类的RDD转换成DataFrame,case类定义了table的结构。

import spark.implicits._
caseclassPerson(name:String,age:Long)

valpeopleDF =
spark.sparkContext.textFile("hdfs://linux01:8020/people.txt").map(_.split(",")).filter(arr=>arr.length==2).map(attributes=>Person(attributes(0),attributes(1).trim.toInt)).toDF(

peopleDF.createOrReplaceTempView("people")
//表的列,比如age,就是通过Person中的属性age反射得到的
spark.sql("select name,age from people where age>20").show

需要注意的是在scala中,我们不能直接用rdd来调用toDF方法,一定要加上

import spark.implicits._

这里的spark指代SparkSession

2.DataSet的创建

Dataset需要提供对应的类型信息。

//先声明一个class:Person
scala>caseclassPerson(name:String,age:Long)
//通过DataFrame转换成DataSet,只需要通过as来指定class即可
scala>valpath="hdfs://linux01:8020/people.json"
scala>valpeopleDS=spark.read.json(path).as[Person]
scala>peopleDS.show()
+---------+---+-----+------+----+
|addr|age|id|name|sex|
+---------+---+-----+------+----+
|shanghai1|21|10001|zhang1|male|
|shanghai2|22|10002|zhang2|male|
|shanghai3|23|10003|zhang3|male|
|shanghai4|24|10004|zhang4|male|
+---------+---+-----+------+----+

3.类型之间的转换总结

RDD、DataFrame、Dataset三者有许多共性,有各自适用的场景常常需要在三者之间转换。
1)DataFrame/Dataset转RDD:

//DataFrame转RDD
valrdd1=testDF.rdd
//DataSet转RDD
valrdd2=testDS.rdd

2)RDD转DataFrame:

importspark.implicits._
valtestDF=rdd.map{line=>(line._1,line._2)}.toDF("col1","col2")

一般用元组把一行的数据写在一起,然后在toDF中指定字段名。
3)RDD转Dataset:

caseclassColtest(col1:String,col2:Int)
objectTestC{
defmain(args:Array[String]):Unit={
    
valconf = newSparkConf().setMaster("local[1]").setAppName("WC")
    
valsparkSession = SparkSession.builder().config(conf).getOrCreate()
    
valrdd = sparkSession.sparkContext.makeRDD(Array(("a",1),("b",1),("a",1)))
    
importsparkSession.implicits._
    
valtestDS = rdd.map{line=>Coltest(line._1,line._2)}.toDS
    
sparkSession.stop()
}
}

可以注意到,定义每一行的类型(caseclass)时,已经给出了字段名和类型
Dataset转DataFrame:
(注意:下面的转换等操作,都是放在object中,caseclass放在object之外)
这个也很简单:

import spark.implicits._
valtestDF=testDS.toDF
//DataFrame转Dataset:
valtestDS2=testDF.as[Coltest]

这种方法就是在给出每一列的类型后,使用as方法,转成Dataset
在使用一些特殊的操作时,一定要加上importspark.implicits._不然toDF、toDS无法使用。

4.RDD、DataFrame、DataSet三者的共性与区别

共性:

1、RDD、DataFrame、Dataset全都是spark平台下的分布式弹性数据集,为处理超大型数据
提供便利
2、三者都有惰性机制,在进行创建、转换,如map方法时,不会立即执行,只有在遇到
Action时,三者才会开始运算
3、三者都会根据spark的内存情况自动缓存运算
4、三者都有partition的概念
5、三者有许多共同的函数,如filter,排序等
6、DataFrame和Dataset均可使用模式匹配获取各个字段的值

区别:

RDD:

RDD不支持sparksql操作

DataFrame:

与RDD和Dataset不同,DataFrame每一行的类型固定为Row,获取各个字段的值的方式为:

testDF.foreach{
line=>
valcol1=line.getAs[String]("col1")
valcol2=line.getAs[Int]("col2")
println(col1+","+col2)
}

不能直接对字段进行访问。
上面的操作还可以写成:

valcol1=line.getString(0)
valcol2=line.getInt(1)

//或者

valcol1=line.getAs[String](0)
valcol2=line.getAs[Int](1)

Dataset:

Dataset和DataFrame拥有完全相同的成员函数,区别只是每一行的数据类型不同。
DataFrame也可以叫Dataset[Row],每一行的类型是Row,不解析,每一行究竟有哪些字段,
各个字段又是什么类型都无从得知,只能用上面提到的getAS方法或者共性中的第七条提到
的模式匹配拿出特定字段
在Dataset中,自定义了caseclass之后可以很自由的获得每一行的每个字段的信息。

testDS.foreach{
line=>
println(line.col1+","+line.col2)
}

你可能感兴趣的:(Spark框架,python,开发语言,后端)