object DataFrameTest {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().master("local").appName("detaSetDemo").getOrCreate()
val dataFrame = spark.read.json("in/user.json")
dataFrame.printSchema()
dataFrame.show()
spark.stop()
}
}
注意:
如果从内存中获取数据,spark 可以知道数据类型具体是什么。
如果是数字,默认作 为 Int 处理;但是从文件中读取的数字,不能确定是什么类型,所以用 bigint 接收,可以和 Long 类型转换,但是和 Int 不能进行转换。
结果展示:
2.2.2 SQL语法
1)读取JSON文件创建DataFrame
val dataFrame = spark.read.json("in/user.json")
2)对DataFrame创建一个临时表
dataFrame.createTempView("user")
// 或
dataFrame.createOrReplaceTempView("user")
3)通过SQL语句实现查询全表
val frame = spark.sql("select * from user")
4)结果展示
frame.show()
注意:
普通临时表是 Session 范围内的,如果想应用范围内有效,可以使用全局临时表。使用全局临时表时需要全路径访问,如:global_temp.people
2.2.3 DSL语法
DataFrame提供一个特定领域语言(domain-specific kanguage, DSL)去管理结构化的数据。可以在Sacla, Java, Python和 R 中使用DSL,使用DSL语法风格不必去创建临时试图了。
1)创建一个DataFrame
val df = spark.read.json("in/user.json")
2)查看DataFrame的Schema信息
df.printSchema()
3)只查看列数据的6种方式
注意:涉及到运算的时候, 每列都必须使用$, 或者采用引号表达式:单引号+字段名
// 输出的6种方式
import spark.implicits._
userDF.select('name,'age).show()
userDF.select("name","age").show()
userDF.select($"name",$"age").show()
userDF.select(userDF("name"),userDF("age")).show()
userDF.select(col("name"),col("age")).show()
userDF.select(column("name"),column("age")).show()
val idColumn = df("id")
4)查看“age”大于“22”的数据
条件过滤可以使用filter,也可以使用where,where的底层调用的也是filter方法。
df.select(userDF("name"),userDF("age"),(userDF("age")+1).as("ageinc"))
.where($"name"=!="zhangsan").show() // where底层也是filter
// .filter($"ageinc">22).show()
5)按照“age”分区,查看数据条数
val countDF = df.groupBy("age").count()
countDF.printSchema()
6)增加列****withColumn
val frame = countDF.withColumn("number",$"count".cast(StringType))
7)修改列名withColumnRenamed
val frame2 = countDF.withColumnRenamed("count","number")
2.2.4 RDD转换为DataFrame
在 IDEA 中开发程序时,如果需要 RDD 与 DF 或者 DS 之间互相操作,那么需要引入import spark.implicits._
这里的 spark 不是 Scala 中的包名,而是创建的 sparkSession 对象的变量名称,所以必 须先创建 SparkSession 对象再导入。这里的 spark 对象不能使用 var 声明,因为 Scala 只支持 val 修饰的对象的引入。
rdd =>DataFrame: rdd.toDF
DataFrame => rdd: df.rdd
2.3 DataSet
DataSet是具有强类型的数据集合,需要提供对于的类型信息。
2.3.1 创建DataSet
object DataSetDemo {
// 1)使用样例类来创建DataSet
case class Point(label:String,x:Double,y:Double)
case class Category(id:Long,name:String)
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().master("local").appName("dataSet").getOrCreate()
val sc = spark.sparkContext
// 重点记忆
import spark.implicits._
// 2)使用基本类型的序列创建DataSet
val points: Seq[Point] = Seq(Point("nj", 23.43, 57.12), Point("bj", 18.21, 199.43), Point("sh", 16.11, 18.3))
val pointDS = points.toDS()
val categories: Seq[Category] = Seq(Category(1, "nj"), Category(2, "bj"))
val categoryDS = categories.toDS()
categoryDS.printSchema()
categoryDS.show()
}
注意:
在实际使用的时候,很少用到把序列转换成DataSet,更多的是通过RDD来得到DataSet。
2.3.2 RDD转换为DataSet
SparkSQL能够自动将包含case类的RDD转换成DataSet,case类定义了table的结构,case类属性通过反射编程了表的列名。case类可以包含如Seq或者Array等复杂的结构。
case class User(name: String, age: Int)
sc.makeRDD(Seq(("zhangsan",18), ("zhaosi",20))).toDS
2.3.3 DataSet转换为RDD
DataSet也是对RDD的封装,所以可以直接获得内部的RDD。
case class User(name: String, age: Int)
val res1 = sc.makeRDD(Seq(("zhangsan",18), ("zhaosi",20))).toDS
val rdd = res1.rdd
2.3.4 DataFrame和DataSet转换
DataFrame => DataSet:as[样例类]
DataSet => DataFrame:toDF
case class User(name: String, age: Int)
val userDF = sc.makeRDD(Seq(("zhangsan",18), ("zhaosi",20))).toDF("name", "age")
val userDS = userDF.as[User]
2.4 RDD、DataFrame、DataSet 三者的关系
2.4.1 相互转化
// RDD <=> DataFrame
val rdd = spark.sparkContext.makeRDD(List(1,"zhangsan",30),(2,"lisi",40))
val df: DataFrame = rdd.toDF("id","name","age")
val rowRDD:RDD[Row] = df.rdd
// DataFrame <=> DataFrame
val ds:Dataset[User] = df.as[User]
val df1:DataFrame = ds.toDF()
// RDD <=> DataSet
rdd.map {
case (id, name, age) =>{
User(id, name, age)
}
}
val userRDD:RAA[User] = ds1.rdd
2.4.2 三者的共性
都是spark平台下的分布式弹性数据集,为处理超大型数据提供便利
都有惰性机制,在创建、转换时,不会立即执行。只有在遇到行动算子时,才会开始运行
有很多共同的函数
DataFrame 和 DataSet 许多操作都需要导入包:import spark.implicits._
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
e 和 DataSet 许多操作都需要导入包:import spark.implicits._
[外链图片转存中…(img-6TUmlSMn-1714505571498)]
[外链图片转存中…(img-yjjngpVu-1714505571499)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!