需求
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)