【Spark學習】RDD基礎練習

需求

1.計算每個學生這兩門課程的總成績,並且排序輸出前5名
2.找出單科成績爲100的學生ID,最終的結果需要集合到一個RDD中
3.求每個學生這兩門成績的平均值
4.合併這個三個表,彙總學生成績並以文本格式存儲,數據彙總爲學生ID,姓名,大數據成績,數學成績,總分,平均分。比如 1002,王一磊,94,94,188,94.0
1001	李正明
1002	王一磊
1003	陳志華
1004	張永麗
1005	趙信
1006	古明遠
1007	劉浩明
1008	沈彬
1009	李子琪
1010	王嘉棟
1011	柳夢文
1012	錢多多

學號	課程	分數
1001	大數據基礎	90			
1002	大數據基礎	94
1003	大數據基礎	100
1004	大數據基礎	99
1005	大數據基礎	90
1006	大數據基礎	94
1007	大數據基礎	100
1008	大數據基礎	93
1009	大數據基礎	89
1010	大數據基礎	78
1011	大數據基礎	91
1012	大數據基礎	84
1001	應用數學	96
1002	應用數學	94
1003	應用數學	100
1004	應用數學	100
1005	應用數學	94
1006	應用數學	80
1007	應用數學	90
1008	應用數學	94
1009	應用數學	84
1010	應用數學	86
1011	應用數學	79
1012	應用數學	91

第一題


 /*
    得到的RDD bigdata及math的數據,取出成績排名前5的學生成績信息
     */
    //創建SparkConf對象
    val conf = new SparkConf().setMaster("local[*]").setAppName("ranking")

    //創建上下文對象
    val sc = new SparkContext(conf)

    //讀取外部存儲文件
    val bigdata: RDD[String] = sc.textFile("D:\\ChromeCoreDownloads\\result_bigdata.txt")
    val math: RDD[String] = sc.textFile("D:\\ChromeCoreDownloads\\result_math.txt")

	//對兩個表進行連接
    val score = bigdata.union(math)

	//將連接後的表score中的每行數據按“\t”分割成集合,並將集合中的學號和分數組合中k-v,學號轉換成Int
    val rdd1 = score.map(_.split("\t")).map(x => (x(0) -> x(2).toInt))
    
    //將key學號相同的value進行聚合,
    //top()底層調用的是takeOrdered(),我們也直接可以用takeOrdered(10)(Ordering.by(e => e._2) 這種寫法叫函數柯里化
    val value = rdd1.reduceByKey(_+_).top(5)(Ordering.by(e => e._2))
   
    //輸出結果
    value.foreach(println)

運行結果
(1003,200)
(1004,199)
(1007,190)
(1002,188)
(1008,187)

第二題

//創建SparkConf對象
    val conf = new SparkConf().setMaster("local[*]").setAppName("ranking")

    //創建上下文對象
    val sc = new SparkContext(conf)

    //讀取外部存儲文件
    val bigdata: RDD[String] = sc.textFile("D:\\ChromeCoreDownloads\\result_bigdata.txt")
    val math: RDD[String] = sc.textFile("D:\\ChromeCoreDownloads\\result_math.txt")

    //取兩個RDD的交集(合併)
    val collect = bigdata.union(math)

    //取出所需要的字段
    val tuple = collect.map(line => {
      val fields = line.split("\t")
      val id = fields(0)
      val sorce = fields(2)
      (id -> sorce)
    })

    //過濾掉成績不是100分的學生
    val res = tupled.distinct().filter(_._2 == "100")
    res.foreach(println)

運行結果

(1007,100)
(1003,100)
(1004,100)

第三題

    //求每個學生這兩門成績的平均值
    //方法一:
    //直接使用combineByKey算子對value值進行轉換,計數,求和等操作,最後map求出平均值
    val res = tuple.combineByKey((_, 1),
      (acc: (Int, Int), v) => (acc._1 + v, acc._2 + 1),
      (acc: (Int, Int), acc2: (Int, Int)) => (acc._1 + acc2._1, acc._2 + acc2._2)
    ).map(a => a._1 -> a._2._1 / a._2._2)

    println("方法一:每個學生這兩門成績的平均值:")
    res.collect().foreach(println)

    println("-------------------------------------")
    /*
    方法二:解題步驟
      1.通過groupByKey算子,對key進行分組
      2.使用mapValues將分組後的k-v值的 v 轉成list,以便於後面使用list的sum size方法
      3.使用map對value值 求和併除以list的大小 從而求出平均值
     */
    val res2 = tuple.groupByKey().mapValues(_.toList).map(a => a._1 -> a._2.sum/a._2.size)

    println("方法二:每個學生這兩門成績的平均值:")
    res2.foreach(println)

運行結果
因爲運行過程中經歷了shuffle階段,導致結果返回順序可能不一致

方法一:每個學生這兩門成績的平均值:
(1005,92)
(1012,87)
(1001,93)
(1009,86)
(1002,94)
(1006,87)
(1010,82)
(1003,100)
(1007,95)
(1008,93)
(1011,85)
(1004,99)
-------------------------------------
方法二:每個學生這兩門成績的平均值:
(1002,94)
(1006,87)
(1010,82)
(1003,100)
(1005,92)
(1008,93)
(1012,87)
(1011,85)
(1001,93)
(1004,99)
(1009,86)
(1007,95)

第四題

  def main(args: Array[String]): Unit = {
    /*
    合併這個三個表,彙總學生成績並以文本格式存儲,
    數據彙總爲學生ID,姓名,大數據成績,數學成績,總分,平均分。比如 1002,王一磊,94,94,188,94.0
     */
    //創建SparkConf對象
    val conf = new SparkConf().setMaster("local[*]").setAppName("ranking")

    //創建上下文對象
    val sc = new SparkContext(conf)

    //讀取外部存儲文件
    val bigdata: RDD[String] = sc.textFile("D:\\ChromeCoreDownloads\\result_bigdata.txt")
    val math: RDD[String] = sc.textFile("D:\\ChromeCoreDownloads\\result_math.txt")
    val stu: RDD[String] = sc.textFile("D:\\ChromeCoreDownloads\\student.txt")

    //將bigdata和math的成績表合併
    val score:RDD[String] = bigdata.union(math)

    val scoreRDD:RDD[(String,Int)] = score.map(line => {
      val field = line.split("\t")
      field(0) -> field(2).toInt
    })

    //求出總成績,平均分,並返回 (學號,(成績,成績,總成績,平均分)) 的結構
    val scoreRes:RDD[(String,(Int,Int,Int,Double))] = scoreRDD.groupByKey().
      mapValues(_.toList).map(a => a._1 -> (a._2(0),a._2(1),a._2.sum,a._2.sum.toDouble/2))

    //轉換stu結構
    val stuRDD:RDD[(String,String)] = stu.map(line => {
      val field = line.split("\t")
      field(0) -> field(1)
    })

    //轉換成最終結構
    val result = stuRDD.join(scoreRes).map(a => (a._1,a._2._1,a._2._2._1,a._2._2._2,a._2._2._3,a._2._2._4))

    //存儲
    result.saveAsTextFile("ouput")

    result.foreach(println)
  }

運行結果

(1002,王一磊,94,94,188,94.0)
(1008,沈彬,93,94,187,93.5)
(1010,王嘉棟,78,86,164,82.0)
(1011,柳夢文,91,79,170,85.0)
(1003,陳志華,100,100,200,100.0)
(1005,趙信,90,94,184,92.0)
(1007,劉浩明,100,90,190,95.0)
(1012,錢多多,84,91,175,87.5)
(1004,張永麗,99,100,199,99.5)
(1006,古明遠,94,80,174,87.0)
(1001,李正明,90,96,186,93.0)
(1009,李子琪,89,84,173,86.5)

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章