题目所需数据集及相应信息描述:
数据集:
1、用户评分数据集ratings.dat:包含了大量用户的历史评分数据。
2、样本评分数据集personalRatings.dat:包含了少数几个用户的个性化评分数据,这些数据反映了某个用户的个性化观影喜好。
3、电影数据集movies.dat:包含了每部电影的相关信息。
注意:
之后依次使用数据集1~3表示上述数据集
数据集结构如下:
1、用户ID::电影ID::评分::时间戳
2、用户ID::电影ID::评分::时间戳
3、电影ID::电影名称::电影类型
(1)movies.dat数据集部分展示:
(2)ratings.dat数据集部分展示:
题目要求:
1、根据数据集3,计算每年发行电影的数量,并进行可视化(柱状图)。
2、根据数据集1,计算每部电影的平均分,并进行可视化(柱状图)。
3、根据数据集1,将电影评分离散化,[0,2)为差,[2-4)为良好,[4-5)为优秀,并进行可视化(饼图)。
4、根据数据集3,统计每种类型电影的数量(若一个电影有多个分类,选择第一个),并进行可视化(饼图)。
5、根据数据集1、2,自行挑选用户(用户id),使用协同过滤算法为其推荐十部电影,无需可视化,只需运行结果。
实验思路及代码:
//计算每年发行电影的数量
val rdd1 = sc.textFile("C:/Users/ch/Desktop/大学/大三阶段/spark/spark实验/课程设计/题目/实验数据集/movies.txt")
//先将每行元素按照::进行分割,然后取出包含年份的那个字段
val rdd2 = rdd1.map(line=>line.split("::")(1))
//获取年份(使用两次反转)
val rdd3 = rdd2.map(line=>line.reverse.take(5))
val rdd4 = rdd3.map(line=>line.reverse.take(4))
//计算每年发行电影的数量
val rdd_result = rdd4.map(word=>(word,1)).reduceByKey(_+_)
//进行格式化
val rdd_show = rdd_result.map(line=>line._1+"年,有"+line._2+"份电影")
//将结果输出到文件夹当中
rdd_show.saveAsTextFile("C:/Users/ch/Desktop/大学/大三阶段/spark/spark实验/课程设计/题目/实验数据集/Test1")
//提取每个电影以及对应的评分,形成一个元组
val rdd3_2 = rdd3_1.map(line=>(line.split("::")(1),line.split("::")(2).toInt))
//对应rdd3_2的value进行操作,key不动
val rdd3_3 = rdd3_2.mapValues(x=>(x,1))
//将相同的电影的评分进行求平均
val rdd3_4 = rdd3_3.reduceByKey((x,y)=>(x._1+y._1,x._2+y._2)).mapValues(x=>x._1/x._2)
//将结果进行保存
rdd3_4.saveAsTextFile("C:/Users/ch/Desktop/大学/大三阶段/spark/spark实验/课程设计/题目/实验数据集/Test3")
//读取数据
val rdd2_1 = sc.textFile("C:/Users/ch/Desktop/大学/大三阶段/spark/spark实验/课程设计/题目/实验数据集/ratings.txt")
//获取评分
val rdd2_2 = rdd2_1.map(line=>line.split("::")(2))
//将评分转化为整数
val rdd2_3 = rdd2_2.map(line=>line.toInt)
//对评分进行离散化
val rdd2_4 = rdd2_3.map(line=>if (line>=0&&line<2) "差" else if(line>=2&&line<4) "良好" else if(line>=4&&line<=5) "优秀")
//将结果进行统计
val rdd2_5 = rdd2_4.map(line=>(line,1)).reduceByKey(_+_)
//将结果进行展示
rdd2_5.foreach(println)
//对movies数据集进行读取
val rdd4_1 = sc.textFile("C:/Users/ch/Desktop/大学/大三阶段/spark/spark实验/课程设计/题目/实验数据集/movies.txt")
//转换成只包含类型数据的RDD
val rdd4_2 = rdd4_1.map(line=>line.split("::")(2))
//当遇到一个电影有多个类型的时候只选取其中第一个类型
val rdd4_3 = rdd4_2.map(line=>line.split(",")(0))
//统计每种类型电影的数量
val rdd4_4 = rdd4_3.map(line=>(line,1)).reduceByKey(_+_)
//将数据保存
rdd4_4.saveAsTextFile("C:/Users/ch/Desktop/大学/大三阶段/spark/spark实验/课程设计/题目/实验数据集/Test4")
//导入文件生成RDD
val rdd5_1 = sc.textFile("C:/Users/ch/Desktop/大学/大三阶段/spark/spark实验/课程设计/题目/实验数据集/ratings.txt"
)
//定义样例类,用来隐式转换
case class Rating(userId:Int,movieId:Int,rating:Float,timestamp:Long)
//反射机制推断RDD来生成DataFrame
val rdd5_2 = rdd5_1.map(line=>Rating(line.split("::")(0).toInt,line.split("::")(1).toInt,line.split("::")(2).toFloat,line.split("::")(3).toLong)).toDF()
//将数据集按4:1划分成训练集和测试集
val Array(train,test) = rdd5_2.randomSplit(Array(0.8,0.2))
//创建model
val model = new ALS().setMaxIter(10).setRegParam(0.03).setUserCol("userId").setItemCol("movieId").setRatingCol("rating")
//训练生成模型
val train_model = model.fit(train)
//模型进行测试
val test_rdd = train_model.transform(test)
//注册为临时表
test_rdd.createOrReplaceTempView("result")
//查找用户id为1的
val result_rdd = spark.sql("select userId,movieId,prediction as rating from result where userId=1")
//按照rating进行降序排列
result_rdd.sort(result_rdd("rating").desc).show()
//读取movies文件
val movie_rdd = sc.textFile("C:/Users/ch/Desktop/大学/大三阶段/spark/spark实验/课程设计/题目/实验数据集/movies.tx
t")
//创建样例类进行隐式转换
case class Movie(movieId:Int,name:String,movieType:String)
val movie_DF = movie_rdd.map(line=>Movie(line.split("::")(0).toInt,line.split("::")(1),line.split("::")(2))).toDF()
//将用户表进行注册
val user_movie = result_rdd.sort(result_rdd("rating").desc)
//注册为临时表
movie_DF.createOrReplaceTempView("movie")
user_movie.createOrReplaceTempView("user")
//两张表进行关联
scala> val result = spark.sql("select movieId,name from movie where movieId = 1287 or movieId=1035 or movieId=3105 or movieId=2355 or movieId=150 or movieId=1 or movieId=1961 or movieId=1028 or movieId=1029 or movieId=1270")
//结果展示(为用户1推荐的电影)
result.map(line=>"MovieId:"+line(0)+","+"MovieName:"+line(1)).show()
result.map(line=>"MovieName:"+line(1)).show()
result.show()