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

在这里插入图片描述

### 回答1: 好的,下面是回复: 【SparkSpark基础练习题(二)是一组用于练习Spark基础知识的题目。这些题目涵盖了Spark的常用操作,包括RDD的创建、转换和行动操作,以及Spark SQL的使用等。通过完这些练习题,可以加深对Spark的理解和掌握,提高Spark编程能力。 ### 回答2: Spark 基础练习题2主要涉及到 Spark Core 和 Spark SQL。其Spark Core 是 Spark基础的模块,它包含了 Spark 的所有基本组件,如 RDDSparkConf、SparkContext 和 Task 等,是使用 Spark 的起点。Spark SQL 则是 Spark 处理结构化数据的核心模块,使用起来非常方便,能够快速地完数据的查询和处理。 针对这道练习题,首先需要了解 Spark Core。Spark Core 最重要的概念是 RDD(Resilient Distributed Dataset,弹性布式数据集),它是一种布式的内存计算模型,也是 Spark 进行数据处理的核心数据结构。在处理数据时,可以使用 RDD 对数据进行转换和操作,比如 map、filter、reduce、join 等操作。SparkContext 是 Spark 的入口点,它负责和集群进行通信,并控制整个应用程序的运行流程。另外,SparkConf 是 Spark 的配置管理器,可以指定一些应用程序的运行参数。 对于 Spark SQL,它采用的是类似于传统 SQL 的结构化查询语言,可以让用户使用 SQL 语句对数据进行查询和析。在 Spark SQL ,最常用的 API 是 DataFrame 和 Dataset。DataFrame 是以列为主导的数据结构,可以将它看是关系型数据库的表,它提供了灵活的编程和数据处理方式。Dataset 则是对 DataFrame 进行的补充,它将 DataFrame 转换类型化的数据集合,提供了更好的类型检查和运行时安全。 综上所述,Spark 基础练习题2需要掌握 Spark Core 和 Spark SQL 的基础概念,并能够用它们进行数据处理和析。需要注意的是,这里只是一个简单的练习题,如果想要真正学好 Spark,还需要深入学习 Spark 的各个模块和外部组件,比如 Spark Streaming、Spark MLlib 等,并掌握其高级应用场景。 ### 回答3: Spark一个开源的布式计算框架,可以用来加速大规模数据处理。在Spark一个重要的概念是Resilient Distributed Datasets(RDD),它是Spark布式数据处理的基本单元。本文将介绍Spark基础练习题(二),帮助大家更好地理解和掌握Spark。 1. 定义RDD RDD是Resilient Distributed Datasets的缩写,它是Spark最基本的布式数据结构。RDD一个只读的、可区、可并行计算的数据集合,支持多种数据源,包括Hadoop Distributed File System(HDFS)、本地文件系统以及其他支持Hadoop InputFormat的数据源。在SparkRDD可以通过各种操作转换和处理,例如map、filter、reduce等,同时支持缓存和持久化,可以提供高效的内存计算和数据共享。 2. RDD的特点 RDD具有以下特点: - 布式处理:RDD可以在Spark集群布式存储、计算和处理数据,支持高效的数据共享和并行计算。 - 可靠性和容错性:RDD具备不可变性,即一旦创建就不能修改。它可以通过记录区的变换历史来实现容错性,如果某个区的数据丢失或失效,可以重新计算。 - 惰性计算:RDD是一种惰性计算模型,支持高效的转换和操作,但只有在需要输出结果时才会真正计算。 - 可缓存和持久化:通过缓存和持久化机制,可以提高计算效率和速度,减少重复计算。 3. 创建RDDSpark,可以通过多种方式创建RDD,常用的有以下几种: - 从本地文件系统创建:使用SparkContext的textFile方法,可以将本地文件系统的文件读入为RDD: ``` val fileRDD = sc.textFile("file:///path/to/file") ``` - 从HDFS创建:使用SparkContext的textFile方法或Hadoop API读取HDFS文件创建RDD: ``` val hdfsRDD = sc.textFile("hdfs://namenode:8020/path/to/file") ``` - 通过并行化集合创建:使用SparkContext的parallelize方法,可以创建一个包含给定集合所有元素的RDD: ``` val listRDD = sc.parallelize(List(1, 2, 3, 4, 5)) ``` 4. RDD的转换操作 RDD支持多种转换操作,常用的有以下几种: - map:对RDD的每个元素应用一个函数,返回一个新的RDD。 ``` val rdd1 = sc.parallelize(List(1, 2, 3, 4, 5)) val rdd2 = rdd1.map(_ * 2) ``` - filter:根据给定的条件过滤RDD的元素,返回一个新的RDD。 ``` val rdd1 = sc.parallelize(List(1, 2, 3, 4, 5)) val rdd2 = rdd1.filter(_ % 2 == 0) ``` - flatMap:对每个元素应用一个函数,并将结果展开为一个新的RDD。 ``` val rdd1 = sc.parallelize(List("Hello world", "Spark is great")) val rdd2 = rdd1.flatMap(_.split(" ")) ``` - union:将两个RDD合并为一个新的RDD。 ``` val rdd1 = sc.parallelize(List(1, 2, 3)) val rdd2 = sc.parallelize(List(4, 5, 6)) val rdd3 = rdd1.union(rdd2) ``` 5. RDD的行动操作 行动操作是指对RDD进行计算并返回结果的操作。常用的行动操作有以下几种: - count:返回RDD元素的个数。 ``` val rdd = sc.parallelize(List(1, 2, 3, 4, 5)) val count = rdd.count() ``` - reduce:对RDD的元素进行累加或拼接等操作。 ``` val rdd = sc.parallelize(List(1, 2, 3, 4, 5)) val sum = rdd.reduce(_ + _) ``` - collect:将RDD的所有元素以数组的形式返回。 ``` val rdd = sc.parallelize(List(1, 2, 3, 4, 5)) val array = rdd.collect() ``` - foreach:对RDD的每个元素应用一个函数。 ``` val rdd = sc.parallelize(List(1, 2, 3, 4, 5)) rdd.foreach(println) ``` 以上是Spark基础练习题(二)的简单介绍,通过熟练掌握和练习这些操作,相信大家能够更好地理解和应用Spark布式计算框架,提高大数据处理的效率和速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值