package com.hicore.exercise
import org.apache.log4j.{Level, Logger}
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession
/**
* @author https://blog.csdn.net/qq_38704184
* @package
* @date 2020/5/13 17:18
* @version 1.0
* @describe
*/
object ExerciseDemo {
Logger.getLogger("org").setLevel(Level.WARN)
def main(args: Array[String]): Unit = {
"""
|12 宋江 25 男 chinese 50
|12 宋江 25 男 math 60
|12 宋江 25 男 english 70
|12 吴用 20 男 chinese 50
|12 吴用 20 男 math 50
|12 吴用 20 男 english 50
|12 杨春 19 女 chinese 70
|12 杨春 19 女 math 70
|12 杨春 19 女 english 70
|13 李逵 25 男 chinese 60
|13 李逵 25 男 math 60
|13 李逵 25 男 english 70
|13 林冲 20 男 chinese 50
|13 林冲 20 男 math 60
|13 林冲 20 男 english 50
|13 王英 19 女 chinese 70
|13 王英 19 女 math 80
|13 王英 19 女 english 70
|""".stripMargin
val session: SparkSession = SparkSession.builder().appName("test").master("local[*]").getOrCreate()
val sc: SparkContext = session.sparkContext
//1:读取文件的数据
val data: RDD[String] = sc.textFile("")
val mapRDD: RDD[Array[String]] = data.map(x => x.split(" "))
//2. 一共有多少个小于20岁的人参加考试?
val count1: Long = mapRDD.filter(x => x(2).toInt < 20).groupBy(_ (1)).count()
//3. 一共有多少个等于20岁的人参加考试?
mapRDD.filter(x => x(2).toInt == 20).groupBy(_ (1)).count()
// 4. 一共有多少个大于20岁的人参加考试?
mapRDD.filter(x => x(2).toInt > 20).groupBy(_ (1)).count()
// 5. 一共有多个男生参加考试?
mapRDD.filter(x => x(3).equals("男")).groupBy(_ (1)).count()
// 6. 一共有多少个女生参加考试?
mapRDD.filter(x => x(3).equals("女")).groupBy(_ (1)).count()
// 7. 12班有多少人参加考试?
mapRDD.filter(x => x(0).equals("12")).groupBy(_ (1)).count()
// 8. 13班有多少人参加考试?
mapRDD.filter(x => x(0).equals("13")).groupBy(_ (1)).count()
// 9. 语文科目的平均成绩是多少?
mapRDD.filter(x => x(4).equals("chinese")).map(x => x(5).toInt).mean()
// 10. 数学科目的平均成绩是多少?
mapRDD.filter(x => x(4).equals("math")).map(x => x(5).toInt).mean()
// 11. 英语科目的平均成绩是多少?
mapRDD.filter(x => x(4).equals("english")).map(x => x(5).toInt).mean()
// 12. 每个人平均成绩是多少
mapRDD.map(x => (x(1), x(5).toInt)).groupByKey().map(t => (t._1, t._2.sum / t._2.size))
// 13. 12班平均成绩是多少?
mapRDD.filter(x => x(0).equals("12")).map(x => x(5).toInt).mean()
// 14. 12班男生平均总成绩是多少?
mapRDD.filter(x => x(0).equals("12") && x(3).equals("男")).map(x => (x(1), x(5).toInt)).groupByKey().map(t => (t._1, t._2.sum)).map(x => x._2).mean()
// 15. 12班女生平均总成绩是多少?
mapRDD.filter(x => x(0).equals("12") && x(3).equals("女")).map(x => (x(1), x(5).toInt)).groupByKey().map(t => (t._1, t._2.sum)).map(x => x._2).mean()
// 16. 13班平均成绩是多少?
mapRDD.filter(x => x(0).equals("13")).map(x => x(5).toInt).mean()
// 17. 13班男生平均总成绩是多少?
mapRDD.filter(x => x(0).equals("13") && x(3).equals("男")).map(x => (x(1), x(5).toInt)).groupByKey().map(t => (t._1, t._2.sum)).map(x => x._2).mean()
// 18. 13班女生平均总成绩是多少?
mapRDD.filter(x => x(0).equals("13") && x(3).equals("女")).map(x => (x(1), x(5).toInt)).groupByKey().map(t => (t._1, t._2.sum)).map(x => x._2).mean()
// 19. 全校语文成绩最高分是多少?
mapRDD.filter(x => x(4).equals("chinese")).map(x => x(5).toInt).max()
// 20. 12班语文成绩最低分是多少?
mapRDD.filter(x => x(4).equals("chinese") && x(0).equals("12")).map(x => x(5).toInt).min()
// 21. 13班数学最高成绩是多少?
mapRDD.filter(x => x(4).equals("math") && x(0).equals("13")).map(x => x(5).toInt).max()
// 22. 总成绩大于150分的12班的女生有几个?
mapRDD.filter(x => x(0).equals("12") && x(3).equals("女")).map(x => (x(1), x(5).toInt)).groupByKey().map(t => (t._1, t._2.sum)).filter(x => x._2 > 150).count()
// 23. 总成绩大于150分,且数学大于等于70,且年龄大于等于19岁的学生的平均成绩是多少?
//val countall: Long = data.map(x=>x.split(" ")).filter(x=>x(2).toInt>=19 && x(3).equals("女")).map(x=>(x(1),x(5).toInt)).groupByKey().map(t=>(t._1,t._2.sum)).filter(x=>x._2>150).count()
val complex1: RDD[(String, Int)] = data.map(x => {
val line: Array[String] = x.split(" ");
(line(0) + "," + line(1) + "," + line(3), line(5).toInt)
})
//(13,李逵,男 , 60)
val complex2: RDD[(String, Int)] = data.map(x => {
val line: Array[String] = x.split(" ");
(line(0) + "," + line(1) + "," + line(2) + "," + line(3) + "," + line(4), line(5).toInt)
})
//(12,宋江,男,chinese , 50)
// 过滤出总分大于150的,并求出平均成绩 (13,李逵,男,(60,1)) (13,李逵,男,(190,3)) 总成绩大于150 (13,李逵,男,63)
val com1: RDD[(String, Int)] = complex1.map(x => (x._1, (x._2, 1))).reduceByKey((a, b) => (a._1 + b._1, a._2 + b._2)).filter(a => (a._2._1 > 150)).map(t => (t._1, t._2._1 / t._2._2))
// 注意:reduceByKey 自定义的函数 是对同一个key值的value做聚合操作
//(12,杨春,女 , 70)
//(13,王英,女 , 73)
//(12,宋江,男 , 60)
//(13,林冲,男 , 53)
//(13,李逵,男 , 63)
//过滤出 数学大于等于70,且年龄大于等于19岁的学生 filter方法返回一个boolean值 【数学成绩大于70并且年龄>=19】 为了将最后的数据集与com1做一个join,这里需要对返回值构造成com1格式的数据
val com2: RDD[(String, Int)] = complex2.filter(a => {
val line: Array[String] = a._1.split(",");
line(4).equals("math") && a._2 >= 70 && line(2).toInt >= 19
}).map(a => {
val line2: Array[String] = a._1.split(",");
(line2(0) + "," + line2(1) + "," + line2(3), a._2.toInt)
})
//(12,杨春,女 , 70)
//(13,王英,女 , 80)
// val common: RDD[(String, (Int, Int))] = com1.join(com2)
// common.foreach(println)
// (12,杨春,女 , (70,70))
// (13,王英,女 , (73,80))
// 使用join函数聚合相同key组成的value元组
// 再使用map函数格式化元素
val result: RDD[(String, Int)] = com1.join(com2).map(a => (a._1, a._2._1))
//(12,杨春,女,70)
//(13,王英,女,73)
session.stop()
}
}