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

在这里插入图片描述

  • 9
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spark RDD(弹性布式数据集)是Spark最基本的数据结构之一,它是一个不可变的布式对象集合,可以在集群进行并行处理。RDD可以从Hadoop文件系统读取数据,也可以从内存的数据集创建。RDD支持两种类型的操作:转换操作和行动操作。转换操作是指对RDD进行转换,生一个新的RDD,而行动操作是指对RDD进行计算并返回结果。RDD具有容错性,因为它们可以在节点之间进行复制,以便在节点故障时恢复数据。 Spark RDD的特点包括: 1. 布式:RDD可以在集群进行并行处理,可以在多个节点上进行计算。 2. 不可变性:RDD是不可变的,一旦创建就不能修改,只能通过转换操作生新的RDD。 3. 容错性:RDD具有容错性,因为它们可以在节点之间进行复制,以便在节点故障时恢复数据。 4. 惰性计算:RDD的计算是惰性的,只有在行动操作时才会进行计算。 5. 缓存:RDD可以缓存到内存,以便在后续操作快速访问。 Spark RDD的转换操作包括: 1. map:对RDD的每个元素应用一个函数,生一个新的RDD。 2. filter:对RDD的每个元素应用一个函数,返回一个布尔值,将返回值为true的元素生一个新的RDD。 3. flatMap:对RDD的每个元素应用一个函数,生一个新的RDD,该函数返回一个序列,将所有序列的元素合并一个新的RDD。 4. groupByKey:将RDD的元素按照key进行组,生一个新的RDD。 5. reduceByKey:将RDD的元素按照key进行组,并对每个的元素进行reduce操作,生一个新的RDDSpark RDD的行动操作包括: 1. count:返回RDD元素的个数。 2. collect:将RDD的所有元素收集到一个数组。 3. reduce:对RDD的所有元素进行reduce操作,返回一个结果。 4. foreach:对RDD的每个元素应用一个函数。 5. saveAsTextFile:将RDD的元素保存到文本文件。 以上就是Spark RDD的详细介绍。 ### 回答2: Apache Spark是一款基于内存的布式计算系统,可以处理大规模数据,其最为重要的就是SparkRDD(Resilient Distributed Datasets,弹性布式数据集),RDDSpark的基本数据结构,是一种类似于数组的布式数据集,可以被多个区,并在集群的多个节点间进行并行计算。RDDSpark提高执行效率和数据可靠性的重要手段。 在SparkRDD具有以下三个特点:弹性、不可变和可区。弹性指RDD能够自动进行数据区和容错,即使节点出现故障,也能够自动从故障的节点复制数据,提高了数据的可靠性和并行计算的效率。不可变指RDD一旦创建就不能够被改变,可以进行转换操作生新的RDD,也可以被缓存到内存以供重复使用。可区则指RDD可以被多个区,实现并行计算。 SparkRDD的API提供了丰富的操作方法,常见的操作包括:转换操作和动作操作。转换操作指对RDD进行转换操作,返回一个新的RDD对象,例如map()、filter()等;动作操作指对RDD进行计算并返回结果,例如reduce()、collect()等。 值得注意的是,RDD是一种惰性求值的数据结构,即当对RDD进行转换操作时并不会立即进行计算,而是当需要RDD进行动作操作时才会进行计算,这种惰性求值的机制可以进一步提高Spark的效率。同时,为了提高计算效率,可以使用RDD的持久化(缓存)功能,将RDD持久化到内存,以便复用。 总之,RDDSpark的核心数据结构,其弹性、不可变和可区的特点以及丰富的API操作方法,为Spark实现高效计算和数据处理提供了重要的支持。 ### 回答3: Spark RDDSpark的核心抽象,代表布式的元素集合,支持多种操作和转换。RDD可以看作是一个不可变的布式内存数据集合,由一些布式的partition(区)组。 1. RDD的特性: - 布式的数据集,可以跨越多个节点进行计算 - 可以并行处理,充利用集群计算资源 - 不可变的数据集,任何对数据集的操作都会生新的数据集 - 支持多种类型的转换操作,如map、filter、reduce、groupByKey等 2. RDD的创建: - 通过外部数据源创建RDD:从HDFS或其他存储系统读取数据创建 - 通过程序的数据结构创建RDD:从内存的数据结构创建 - 通过其他RDD转换创建RDD:通过对已有的RDD进行转换操作创建 3. RDD的转换: RDD支持多种类型的操作和转换,如map、filter、reduce、groupByKey等。这些转换操作不会立即执行,而是记录下来,等到需要输出结果时才会真正执行。 4. RDD的行动: 行动操作是指对RDD进行计算并返回结果的操作,如count、collect等。行动操作会立即触发RDD的计算过程。 5. RDD的缓存: RDD支持缓存操作,将一个RDD的结果缓存在内存,提高后续对该RDD的计算效率。缓存可以在计算过程多次使用,通过unpersist清理缓存。 6. RDD的持久化: 当RDD的计算过程非常复杂时,可以将计算过程得到的RDD进行持久化以便后续使用。持久化可以选择将RDD保存在磁盘或者内存,也可以将RDD复制到多个节点上以保障数据的可靠性。 7. RDD的checkpoint: RDD的checkpoint是指将RDD的计算结果保存在HDFS或其他布式存储系统,以便后续查询和还原数据集。在计算复杂的RDD时,使用checkpoint可以避免计算过程数据丢失的问题。 总的来说,Spark RDDSpark布式计算的核心特性,其提供对大规模数据集的布式处理能力,以及丰富的操作和转换方式,使得程序员可以轻松地处理海量数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值