每天天都在努力學(xué)習(xí)的我們
前言
????????本篇博客講解的內(nèi)容依舊是使用Spark進(jìn)行相關(guān)的數(shù)據(jù)分析,按理來(lái)說(shuō)數(shù)據(jù)分析完之后應(yīng)該搞一搞可視化的,由于目前時(shí)間緊張,顧不得學(xué)習(xí)可視化了,先來(lái)看一下此次的內(nèi)容把。
????????在Kaggle數(shù)據(jù)平臺(tái)下載了數(shù)據(jù)集albunms.csv,里面包含了的主要字段如下,先來(lái)看一下。
使用Spark讀取csv
????????spark讀取csv的方式有兩種,一種是使用rdd進(jìn)行讀取csv,然后創(chuàng)建RDD對(duì)象。另一種是使用spark SQL進(jìn)行讀取,創(chuàng)建DataFrame對(duì)象。本篇博客使用Spark SQL進(jìn)行讀取文件,RDD和Data Frame處理數(shù)據(jù)。
????????csv文件我們都知道,","分隔符,但是讀取csv文件的同時(shí)也要注意是否有無(wú)表頭,表頭字段類型。下面來(lái)看一下Spark SQL讀取csv。
private
val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("Spark SQL") private
val sparkContext = new SparkContext(sparkConf)
private val sparkSession: SparkSession =SparkSession.builder().config(sparkConf).getOrCreate()
import sparkSession.implicits._ def
Transform_demo()={
//使用sparksession 讀取csv文件,此csv文件有表頭
val dataFrame = sparkSession.read.format("com.databricks.spark.csv")
//有無(wú)表頭
.option("header", true)
//是否自動(dòng)推斷表頭類型
.option("inferSchema", false)
//分隔符
.option("delimiter", ",")
//csv文件的地址
.csv("date/albums.csv")
dataFrame
}
統(tǒng)計(jì)各類型專輯的數(shù)量
????????思路:
????????各類型專輯的數(shù)量 ==》根據(jù)專輯類型(genre)分組,求出專輯類型的總和
????????使用spark SQL進(jìn)行處理
def genre_demo() = {
//統(tǒng)計(jì)各個(gè)類型專輯的數(shù)量
val unit = Transform_demo()
.select($"genre")
.groupBy($"genre")
.count()
.sort($"count".desc)
.show() }
????????在Spark SQL中使用group by的時(shí)候,提供了group by之后的操作,比如
????????max(colNames:String*):獲取分組中指定字段或者所有的數(shù)字類型字段的最大值,只能作用于數(shù)字型字段。
????????min(colNames:String*):獲取分組字段或者所有的數(shù)字類型字段的最小值,只能作用于數(shù)字類型的字段。
????????mean(colName:String*):獲取分組中指定字段或者所有數(shù)字類型字段的平均值,只能作用于數(shù)據(jù)類型的字段
????????sum(colNames:String*):獲取分組中指定字段或者所有數(shù)字類型字段的累加值,只能作用于數(shù)字類型的字段
????????count():獲取分組中的元素個(gè)數(shù)
????????根據(jù)genre字段分組后,求出專輯類型的個(gè)數(shù),對(duì)專輯類型的個(gè)數(shù)進(jìn)行排序。如果需要導(dǎo)入到文件里面,那么需要.write。
使用Rdd進(jìn)行處理
?????def genre_demo() = {
val value = Transform_demo()
.select($"genre")
.rdd
.map(v => (v(0), 1))
.reduceByKey(_ + _)
.sortBy(_._2,false)
????????展示一下上面的流程圖把
統(tǒng)計(jì)各類型專輯的銷量總數(shù)
思路:
????????根據(jù)專輯類型分組,分組之后,計(jì)算num_of_sales專輯銷量總和。
????????如果是spark SQL的話,流程應(yīng)該是這樣的。
????????dataFrame => select => group by => sum()
????????來(lái)看一下代碼
def countByNum_sales()={
Transform_demo()
.select($"genre",$"num_of_sales")
.withColumn("num_of_sales",col("num_of_sales")
.cast("Integer"))
.groupBy("genre")
.sum("num_of_sales")
.orderBy($"sum(num_of_sales)".desc)
.show() }
????????如果在group by后面直接sum求和,那么是會(huì)報(bào)錯(cuò)的,因?yàn)樵谧铋_始的時(shí)候,我們并沒有讓系統(tǒng)自動(dòng)推斷表頭的數(shù)據(jù)類型,默認(rèn)為String類型,因此需要先轉(zhuǎn)換為整型,然后對(duì)其進(jìn)行操作。
????????來(lái)看一下RDD的代碼
def countByNum_sales()={
val value = Transform_demo()
.select($"genre", $"num_of_sales")
.rdd
.map(v => (v(0).toString, v(1).toString.toInt))
.reduceByKey(_ + _) .sortBy(_._2, false)
value }
統(tǒng)計(jì)近20年每年發(fā)行的專輯數(shù)量和單曲數(shù)量
????????思路:
????????根據(jù)年份分組(year_of_pub),求每年發(fā)行的專輯數(shù)量和單曲數(shù)量。
????????單曲數(shù)量很簡(jiǎn)單(num_of_tracks)累加,但是專輯數(shù)量怎么表示呢?
????????注意一下,num_of_tracks字段:每張專輯中的單曲數(shù)量,什么意思呢?來(lái)看一下這樣的表示
????????(num_of_tracks,1) =》 (每張專輯的單曲數(shù)量,專輯數(shù)量)
????????這個(gè)1就代表著專輯的數(shù)量。
????????用RDD來(lái)理一下思路,(年份,(每張專輯的單曲數(shù)量,1)) ==>經(jīng)過(guò)reduceByKey (年份,(每年發(fā)行的單曲數(shù)量,每年發(fā)行的專輯數(shù)量))
def Countbytracks() ={
//統(tǒng)計(jì)近20年每年發(fā)行的專輯數(shù)量和單曲數(shù)量;
//每年發(fā)行的單曲數(shù)量 num_of_tracks 專輯數(shù)量怎么算呢?
//num_of_tracks: 每張專輯中單曲數(shù)量
//(1張專輯,專輯發(fā)行的單曲數(shù)量)
val array = Transform_demo()
.select($"year_of_pub", $"num_of_tracks")
.rdd
.map(v => (v(0).toString.toInt, (v(1).toString.toInt, 1)))
.reduceByKey((x, y) => (x._1 + y._1, (x._2 + y._2)))
.sortByKey()
array }
來(lái)看一下流程圖
分析總銷量前五的專輯類型的各年份銷量
????????思路:
????????首先求出來(lái)總銷售量前五的專輯類型,然后取前五個(gè)數(shù)量最多的,之后在這個(gè)五個(gè)數(shù)量最多的專輯類型里面計(jì)算每年的銷量。
????????首先獲取總銷售量前五的專輯類型
def get_genre() = {
//先獲取總銷售量前5的專輯類型
val array = Transform_demo()
.select($"genre", $"num_of_sales")
.withColumn("num_of_sales", col("num_of_sales").cast("Integer"))
.groupBy($"genre")
.sum("num_of_sales")
.orderBy($"sum(num_of_sales)".desc)
.rdd
.map(v => v(0).toString)
.take(5)
array }
????????首先更改字段類型,根據(jù)銷售類型(genre)分組,找到銷量最多的銷售類型.經(jīng)過(guò)map轉(zhuǎn)換之后取前五個(gè)銷售類型。
????????獲取總銷量前5的專輯類型的各年份銷量
def per_year_sales()={
val genre_list = get_genre()
val value = Transform_demo()
.select($"genre", $"year_of_pub", $"num_of_sales")
.rdd
.filter(v => genre_list.contains(v(0)) )
.map(v => ((v(0).toString, v(1).toString), v(2).toString.toInt))
.reduceByKey(_ + _)
value }
????????如果單獨(dú)看上面的代碼看不懂,那么來(lái)看一下下面的流程圖把,一定明明白白。
總結(jié)
????????關(guān)于這篇音樂分析項(xiàng)目就到此為止了。
????????關(guān)于對(duì)數(shù)據(jù)的基本處理已經(jīng)有了些眉目,接下來(lái)就是不斷的練習(xí)練習(xí)。
????????之后還有會(huì)其它的項(xiàng)目,我們最終的Boss項(xiàng)目就是離線數(shù)倉(cāng)項(xiàng)目的建設(shè)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-482369.html
????????最后,希望我的她可以越來(lái)越好,天天開心文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-482369.html
到了這里,關(guān)于基于Spark的音樂專輯數(shù)據(jù)分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!