官术网_书友最值得收藏!

12.3 通過RDD分析各種類型的最喜愛電影TopN及性能優化技巧

通過RDD分析大數據電影點評系統各種類型的最喜愛電影TopN。本節分析最受男性喜愛的電影Top10和最受女性喜愛的電影Top10。

評級文件ratings.dat的格式描述如下。

1.  UserID::MovieID::Rating::Timestamp
2.  用戶ID、電影ID、評分數據、時間戳

用戶文件users.dat的格式描述如下。

1.  UserID::Gender::Age::Occupation::Zip-code
2.  用戶ID、性別、年齡、職業、郵編代碼

單單從評分數據ratings中無法計算出最受男性或者女性喜愛的電影Top10,因為該RDD中沒有性別Gender信息,如果需要使用性別Gender信息進行性別Gender的分類,此時一定需要聚合。當然,我們力求聚合的使用是mapjoin(分布式計算的殺手是數據傾斜,Mapper端的Join是一定不會數據傾斜的),這里可否使用mapjoin呢?不可以,因為用戶的數據非常多!所以,這里要使用正常的Join,此處的場景不會數據傾斜,因為用戶一般都均勻地分布。

最受男性喜愛的電影Top10和最受女性喜愛的電影Top10分析需注意以下事項。

(1)因為要再次使用電影數據的RDD,所以復用了前面Cache的ratings數據。

(2)在根據性別過濾出數據后,關于TopN部分的代碼直接復用前面的代碼就行了。

(3)要進行Join,需要key-value。

(4)在進行Join的時候,通過take等方法注意Join后的數據格式(3319,((3319, 50, 4.5),F))。

(5)使用數據冗余來實現代碼復用或者更高效地運行,這是企業級項目的一個非常重要的技巧!

大數據電影點評系統中,統計最受男性喜愛的電影Top10和最受女性喜愛的電影Top10,我們先分別過濾出男性、女性相關的數據,具體實現思路如下:

(1)對ratings中的(用戶ID,電影ID,評分)元組進行map轉換,格式化成Key-Value,即(用戶ID,(用戶ID,電影ID,評分))。

(2)對usersRDD中的每行數據按"::"分隔符分割,然后進行map轉換,格式化成Key-Value,即(用戶ID,性別)。

(3)將(用戶ID,(用戶ID,電影ID,評分))與(用戶ID,性別)進行Join生成新的genderRatings RDD。格式為:(用戶ID,((用戶ID,電影ID,評分),性別)),性別,并且進行Cache緩存。

(4)對genderRatings RDD進行過濾轉換,從元組(x._1用戶ID,(x._2._1(用戶ID,電影ID,評分),x._2._2性別))過濾出x._2._2性別等于男性的數據。然后進行map轉換為x._2._1,即轉換成(用戶ID,電影ID,評分)格式,生成maleFilteredRatings。

(5)對genderRatings RDD進行過濾轉換,從元組(x._1用戶ID,(x._2._1(用戶ID,電影ID,評分),x._2._2性別))過濾出x._2._2性別等于女性的數據。然后進行map轉換為x._2._1,即轉換成(用戶ID,電影ID,評分)格式,生成femaleFilteredRatings。

從大數據電影點評系統中過濾男性、女性相關的數據的代碼如下。

1.  val male = "M"
2.  val female = "F"
3.  val genderRatings = ratings.map(x => (x._1, (x._1, x._2, x._3))).join(
4.    usersRDD.map(_.split("::")).map(x => (x(0), x(1)))).cache()
5.  genderRatings.take(2).foreach(println)
6.  val maleFilteredRatings: RDD[(String, String, String)] = gender
    Ratings.filter(x => x._2._2.equals("M")).map(x => x._2._1)
7.  val femaleFilteredRatings = genderRatings.filter(x => x._2._2.equals
    ("F")).map(x => x._2._1)

在IDEA中運行代碼,打印出genderRatings的數據,取10個數據,格式為:(用戶ID,((用戶ID,電影ID,評分),性別)),結果如下。

1.  (3319,((3319,32,5),F))
2.  (3319,((3319,50,4.5),F))
3.  (3319,((3319,163,4.5),F))
4.  (3319,((3319,180,5),F))
5.  (3319,((3319,296,5),F))
6.  (3319,((3319,318,5),F))
7.  (3319,((3319,405,4),F))
8.  (3319,((3319,914,4.5),F))
9.  (3319,((3319,1088,4),F))
10. (3319,((3319,1136,5),F))

電影點評系統用戶行為分析,統計所有電影中最受男性喜愛的電影Top10,具體實現思路如下:

(1)將性別為男的用戶過濾以后的數據(用戶ID,電影ID,評分)進行map轉換,格式化成為Key-Value的方式,即(電影ID,(評分,1))。

(2)使用reduceByKey算子對Value值進行匯聚轉換,對兩個具有相同Key值,而Value不同的元組,如(電影ID,(x.評分,x.1)),(電影ID,(y.評分,y.1)),計算得出(x的評分+y的評分,x的計數+y的計數),轉換以后Key是電影ID,Value是(總的評分,總的點評人數),格式化成為Key-Value,即(電影ID,(總評分,總點評人數))。

(3)reduceByKey算子執行完畢,接下來進行map轉換操作,交換Key-Value值,并且計算出電影平均分=總評分/總點評人數,即將(電影ID,(總評分,總點評人數))轉換成((總評分/總點評人數),電影ID),然后使用sortByKey(false)算子按電影平均分降序排列。

(4)再次進行Key和Value的交換,打印輸出。使用map轉換函數將((總評分/總點評人數),電影ID)進行交換,轉換為(電影ID,(總評分/總點評人數)),再通過take(10)算子獲取所有電影中最受男性喜愛的電影Top10,進行打印輸出。

在所有電影中分析最受男性喜愛的電影Top10的代碼如下。

1.  println("所有電影中最受男性喜愛的電影Top10:")
2.      maleFilteredRatings.map(x=>(x._2,(x._3.toDouble, 1)))//格式化成為Key-Value
3.        .reduceByKey((x, y) => (x._1 + y._1,x._2 + y._2))
          //對Value進行reduce操作,分別得出每部電影的總的評分和總的點評人數
4.        .map(x => (x._2._1.toDouble / x._2._2, x._1))  //求出電影平均分
5.        .sortByKey(false) //降序排列
6.        .map(x => (x._2, x._1))
7.        .take(10)              //取Top10
8.        .foreach(println) //打印到控制臺

在IDEA中運行代碼,結果如下。

1.  所有電影中最受男性喜愛的電影Top10:
2.  (855,5.0)
3.  (6075,5.0)
4.  (1166,5.0)
5.  (3641,5.0)
6.  (1045,5.0)
7.  (4136,5.0)
8.  (2538,5.0)
9.  (7227,5.0)
10. (8484,5.0)
11. (5599,5.0)

同樣地,在電影點評系統用戶行為分析中,我們可以統計所有電影中最受女性喜愛的電影Top10,具體實現思路和最受男性喜愛的電影Top10類似,這里不再贅述。

從所有電影中分析最受女性喜愛的電影Top10的代碼如下。

1.  println("所有電影中最受女性喜愛的電影Top10:")
2.   femaleFilteredRatings.map(x=>(x._2,(x._3.toDouble,1)))//格式化成為Key-Value
3.     .reduceByKey((x, y) => (x._1 + y._1,x._2 + y._2))
       //對Value進行reduce操作,分別得出每部電影的總的評分和總的點評人數
4.     .map(x => (x._2._1.toDouble / x._2._2, x._1))  //求出電影平均分
5.     .sortByKey(false) //降序排列
6.     .map(x => (x._2, x._1))
7.     .take(10)             //取Top10
8.     .foreach(println) //打印到控制臺

在IDEA中運行代碼,結果如下。

1.  所有電影中最受女性喜愛的電影Top10:
2.  [Stage 43:=================================>  7 + 1) / 8](789,5.0)
3.  (855,5.0)
4.  (32153,5.0)
5.  (4763,5.0)
6.  (26246,5.0)
7.  (2332,5.0)
8.  (503,5.0)
9.  (4925,5.0)
10. (8767,5.0)
11. (44657,5.0)
主站蜘蛛池模板: 海南省| 清水县| 南召县| 沙坪坝区| 河池市| 长泰县| 松桃| 甘孜县| 牙克石市| 鹤山市| 抚顺县| 濮阳县| 正安县| 光泽县| 修水县| 广丰县| 得荣县| 曲松县| 壶关县| 南昌县| 陆良县| 马关县| 静海县| 富裕县| 方城县| 罗田县| 湘潭市| 洞口县| 正阳县| 蒙城县| 泾源县| 合阳县| 万源市| 鹿邑县| 西乌珠穆沁旗| 宁都县| 金秀| 绵阳市| 绥化市| 互助| 冷水江市|