DataFrame概述與使用
一、 概述:
DataFrame是一個分散式資料集,可以理解為關係型資料庫一張表,由欄位和欄位型別、欄位值按列組織,且支援四種語言,在Scala API中可以理解為: FataFrame=Dataset[ROW]
注:DataFrame產生於V1.3之後,在V1.3前為SchemaRDD,在V1.6以後又新增了Dataset
二、DataFrame vs RDD 差異:
概念 : 兩個都是分散式容器,DF理解是一個表格除了RDD資料以外還有Schema,也支援複雜資料型別(map..)
API : DataFrame提供的API比RDD豐富 支援map filter flatMap .....
資料結構:RDD知道型別沒有結構, DF提供Schema資訊 有利於最佳化,效能上好
底層 :基於執行環境不一樣,RDD開發的Java/Scala API執行底層環境JVM,
DF在SparkSQL中轉換成邏輯執行計劃(locaical Plan)和物理執行計劃(Physical Plan)中間自身最佳化功能,效能差異大
三、json檔案操作
[hadoop@hadoop001 bin]$./spark-shell --master local[2] --jars ~/software/mysql-connector-java-5.1.34-bin.jar
-- 讀取json檔案
scala>val df = spark.read.json("file:///home/hadoop/data/people.json")
18/09/02 11:47:20 WARN ObjectStore: Failed to get database global_temp, returning NoSuchObjectException
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]
-- 列印schema資訊
scala> df.printSchema
root
|-- age: long (nullable = true) -- 欄位 型別 允許為空
|-- name: string (nullable = true)
-- 列印欄位內容
scala> df.show
+----+-------+
| age| name|
+----+-------+
|null|Michael|
| 30| Andy|
| 19| Justin|
+----+-------+
-- 列印查詢欄位
scala> df.select("name").show
+-------+
| name|
+-------+
|Michael|
| Andy|
| Justin|
+-------+
-- 單引號,存在隱式轉換
scala> df.select('name).show
+-------+
| name|
+-------+
|Michael|
| Andy|
| Justin|
+-------+
-- 雙引號隱式轉換不識別
scala> df.select("name).show
<console>:1: error: unclosed string literal
df.select("name).show
^
-- 年齡計算,NULL無法計算
scala> df.select($"name",$"age" + 1).show
+-------+---------+
| name|(age + 1)|
+-------+---------+
|Michael| null|
| Andy| 31|
| Justin| 20|
+-------+---------+
-- 年齡過濾
scala> df.filter($"age" > 21).show
+---+----+
|age|name|
+---+----+
| 30|Andy|
+---+----+
-- 年齡分組 彙總
scala> df.groupBy("age").count.show
+----+-----+
| age|count|
+----+-----+
| 19| 1|
|null| 1|
| 30| 1|
+----+-----+
-- 建立一個臨時檢視
scala> df.createOrReplaceTempView("people")
scala>spark.sql("select * from people").show
+----+-------+
| age| name|
+----+-------+
|null|Michael|
| 30| Andy|
| 19| Justin|
+----+-------+
四、DataFrame物件上Action操作
-- 定義case class 用來建立Schema
case class Student(id:String,name:String,phone:String,Email:String)
-- RDD與DF反射方式實現
val students = sc.textFile("file:///home/hadoop/data/student.data").map(_.split("\\|")).map(x=>Student(x(0),x(1),x(2),x(3))).toDF()
-- 列印DF資訊
students.printSchema
-- show(numRows: Int, truncate: Boolean)
-- numRows擷取前20行和truncate讀取前20字串
-- students.show(5,false) 讀取前五行和所有字串
scala> students.show
+---+--------+--------------+--------------------+
| id| name| phone| Email|
+---+--------+--------------+--------------------+
| 1| Burke|1-300-746-8446|ullamcorper.velit...|
| 2| Kamal|1-668-571-5046|pede.Suspendisse@...|
| 3| Olga|1-956-311-1686|Aenean.eget.metus...|
| 4| Belle|1-246-894-6340|vitae.aliquet.nec...|
| 5| Trevor|1-300-527-4967|dapibus.id@acturp...|
| 6| Laurel|1-691-379-9921|adipiscing@consec...|
| 7| Sara|1-608-140-1995|Donec.nibh@enimEt...|
| 8| Kaseem|1-881-586-2689|cursus.et.magna@e...|
| 9| Lev|1-916-367-5608|Vivamus.nisi@ipsu...|
| 10| Maya|1-271-683-2698|accumsan.convalli...|
| 11| Emi|1-467-270-1337|est@nunc.com|.......|
| 12| Caleb|1-683-212-0896|Suspendisse@Quisq...|
| 13|Florence|1-603-575-2444|sit.amet.dapibus@...|
| 14| Anika|1-856-828-7883|euismod@ligulaeli...|
| 15| Tarik|1-398-171-2268|turpis@felisorci.com|
| 16| Amena|1-878-250-3129|lorem.luctus.ut@s...|
| 17| Blossom|1-154-406-9596|Nunc.commodo.auct...|
| 18| Guy|1-869-521-3230|senectus.et.netus...|
| 19| Malachi|1-608-637-2772|Proin.mi.Aliquam@...|
| 20| Edward|1-711-710-6552|lectus@aliquetlib...|
+---+--------+--------------+--------------------+
only showing top 20 rows
-- students.head(5) 返回前幾行資料
scala> students.head(5).foreach(println)
[1,Burke,1-300-746-8446,ullamcorper.velit.in@ametnullaDonec.co.uk]
[2,Kamal,1-668-571-5046,pede.Suspendisse@interdumenim.edu]
[3,Olga,1-956-311-1686,Aenean.eget.metus@dictumcursusNunc.edu]
[4,Belle,1-246-894-6340,vitae.aliquet.nec@neque.co.uk]
[5,Trevor,1-300-527-4967,dapibus.id@acturpisegestas.net]
-- 查詢具體欄位
scala> students.select("id","name").show(5)
+---+------+
| id| name|
+---+------+
| 1| Burke|
| 2| Kamal|
| 3| Olga|
| 4| Belle|
| 5|Trevor|
+---+------+
-- 修改欄位取別名
scala> students.select($"name".as("new_name")).show(5)
+--------+
|new_name|
+--------+
| Burke|
| Kamal|
| Olga|
| Belle|
| Trevor|
+--------+
--查詢id大於五
scala> students.filter("id>5").show(5)
+---+------+--------------+--------------------+
| id| name| phone| Email|
+---+------+--------------+--------------------+
| 6|Laurel|1-691-379-9921|adipiscing@consec...|
| 7| Sara|1-608-140-1995|Donec.nibh@enimEt...|
| 8|Kaseem|1-881-586-2689|cursus.et.magna@e...|
| 9| Lev|1-916-367-5608|Vivamus.nisi@ipsu...|
| 10| Maya|1-271-683-2698|accumsan.convalli...|
+---+------+--------------+--------------------+
-- 查詢名稱為空或者名稱為NULL(filter=where)
scala> students.filter("name=''or name='NULL'").show(false)
+---+----+--------------+--------------------------+
|id |name|phone |Email |
+---+----+--------------+--------------------------+
|21 | |1-711-710-6552|lectus@aliquetlibero.co.uk|
|22 | |1-711-710-6552|lectus@aliquetlibero.co.uk|
|23 |NULL|1-711-710-6552|lectus@aliquetlibero.co.uk|
+---+----+--------------+--------------------------+
-- 查詢ID大於5且名稱模糊查詢
scala> students.filter("id>5 and name like 'M%'").show(5)
+---+-------+--------------+--------------------+
| id| name| phone| Email|
+---+-------+--------------+--------------------+
| 10| Maya|1-271-683-2698|accumsan.convalli...|
| 19|Malachi|1-608-637-2772|Proin.mi.Aliquam@...|
+---+-------+--------------+--------------------+
-- 按照名稱升序排序且不等於空
scala> students.sort($"name").select("id","name").filter("name <> ''").show(3)
+---+-----+
| id| name|
+---+-----+
| 16|Amena|
| 14|Anika|
| 4|Belle|
+---+-----+
-- 按照名稱倒敘排序(sort = orderBy)
scala> students.sort($"name".desc).select("name").show(5)
+------+
| name|
+------+
|Trevor|
| Tarik|
| Sara|
| Olga|
| NULL|
+------+
-- 年齡分組 彙總
scala> students.groupBy("age").count().show
+----+-----+
| age|count|
+----+-----+
| 19| 1|
|null| 1|
| 30| 1|
+----+-----+
-- 聚合函式使用
scala> students.agg("id" -> "max", "id" -> "sum").show(false)
+-------+-------+
|max(id)|sum(id)|
+-------+-------+
|9 |276.0 |
+-------+-------+
-- join操作,using模式seq指定多個欄位
students.join(students2, Seq("id", "name"), "inner")
-- DataFrame的join操作有inner, outer, left_outer, right_outer, leftsemi型別
-- 指定型別,指定join的型別
students.join(students2 , students("id" ) === students2( "t1_id"), "inner")
五、DataFrame API實現檔案操作
1.maven依賴下載
<spark.version>2.3.1</spark.version>
<!-- 新增Spark Core的dependency -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
<!-- 新增Spark SQL的dependency -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>${spark.version}</version>
</dependency>
2、IDEA實現方式:
package com.zrc.ruozedata.sparkSQL
import org.apache.spark.sql.types.{IntegerType, StringType, StructField, StructType}
import org.apache.spark.sql.{Row, SparkSession}
object SparkSQL001 extends App {
/*
* RDD與DataFrame反射方式實現(一)
* 建立RDD --> DataFrema
* 利用case class建立Schema,來解析輸出文字每一行資訊
*/
val spark = SparkSession.builder()
.master("local[2]")
.appName("SparkSQL001")
.getOrCreate() // 操作hive新增
val infos = spark.sparkContext.textFile("file:///F:/infos.txt")
/*
import spark.implicits._
val infoDF = infos.map(_.split(",")).map(x=>Info(x(0).toInt,x(1),x(2).toInt)).toDF()
infoDF.show()
*/
/*
* RDD與DataFrame使用StructType方式實現(二)
* StructType構造了StructField方法傳入name和dataType
* 每一個欄位就是為一個StructField
* Schema和RDD透過createDataFrame方法作用起來
*/
// 注意透過ROW獲取的需要轉換對應型別
val infoss = infos.map(_.split(",")).map(x=>Row(x(0).trim.toInt,x(1),x(2).trim.toInt))
val fields = StructType(
Array(
StructField("id",IntegerType,true),
StructField("name",StringType,true),
StructField("age",IntegerType,true)
)
)
val schema = StructType(fields)
val infoDF = spark.createDataFrame(infoss,schema)
infoDF.show()
spark.stop()
}
// case class Info (id:Int,name:String,age:Int)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31441024/viewspace-2213491/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- PySpark DataFrame教程與演示Spark
- panda.DataFrame.loc 使用詳解
- 使用Pandas DataFrame輸出報告
- pandas中dataframe與dict相互轉換
- Spark SQL中的RDD與DataFrame轉換SparkSQL
- pandas | DataFrame中的排序與彙總方法排序
- Scala - DataFrame
- XSD 使用概述
- pandas | 詳解DataFrame中的apply與applymap方法APP
- JWT概述和使用JWT
- vLLM與PagedAttention:全面概述
- Oracle Stream概述與配置Oracle
- Pandas - DataFrame.loc
- 【pyspark】dataframe常用操作Spark
- Pandas DataFrame常用方法
- 資料分析: DataFrame
- reids(2)概述與安裝
- fasthttp 概述與 Hello World(本文)ASTHTTP
- PySpark筆記(三):DataFrameSpark筆記
- Spark建立空的DataFrameSpark
- python pandas DataFrame-A 更新 DataFrame-B中指定列相同的資料Python
- java概述與第一個程式Java
- 3.1 以太坊背景與概念概述
- Oracle 備份 與 恢復 概述Oracle
- Pandas使用DataFrame進行資料分析比賽進階之路(一)
- Java StringTokenizer 類使用方法概述Java
- 給 dataframe 列重新命名
- DataFrame刪除複合索引索引
- SparkSQL /DataFrame /Spark RDD誰快?SparkSQL
- dataframe 萬用字元篩選字元
- Python中建立DataFrame的方法Python
- Spark DataFrame的groupBy vs groupByKeySpark
- 【pandas學習筆記】DataFrame筆記
- 元宇宙系統概述與介紹元宇宙
- 概述看是相似的COPY 與 ADD 命令
- C# 列舉與位列舉概述C#
- Vivado使用技巧(29):約束功能概述
- Vivado使用技巧(18):模擬功能概述