【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)

【Spark学习】RDD基础练习_第1张图片

你可能感兴趣的:(【Spark学习】RDD基础练习)