Spark课程设计——电影推荐系统

2023-11-16

题目所需数据集及相应信息描述:
数据集:
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),使用协同过滤算法为其推荐十部电影,无需可视化,只需运行结果。

实验思路及代码:

(1)第一小题思路(流程图)
在这里插入图片描述
代码:

//计算每年发行电影的数量
 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")

结果展示:
在这里插入图片描述

(2)第二小题思路
在这里插入图片描述
代码:

//提取每个电影以及对应的评分,形成一个元组
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")

结果展示:
在这里插入图片描述

(3)第三小题思路
在这里插入图片描述
代码:

//读取数据
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)

结果展示:
在这里插入图片描述

(4)第四小题思路:
在这里插入图片描述
代码:

//对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")

结果展示:
在这里插入图片描述

(5)第五小题思路:
在这里插入图片描述
代码:

//导入文件生成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()

结果展示:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spark课程设计——电影推荐系统 的相关文章

随机推荐

  • k8s配置StatefulSet解读

    什么是StatefulSet 直接参考原博客 k8s配置StatefulSet StatefulSet和Deployment一样 可以保证集群中运行指定个数的pod 也支持横向扩展 但每个pod都是不可互换的 无论pod被怎样调度 它们的标
  • Python学习-----无序序列1.0(字典的创建、查看、添加、修改、删除/替换)

    目录 前言 字典是什么 字典的特点 1 字典的创建 1 直接创建 2 dict 函数创建 2 字典的查询 1 get 函数 2 获取字典一组内容 3 字典键值对的添加 1 直接添加 2 setdefault 函数 4 字典的修改 updat
  • 基础回顾5

    JVM JRE JDK JVM表示java虚拟机 Java程序需要运行在虚拟机上 不同平台有自己的虚拟机 所以java可以实现跨平台运行 JRE表示java运行环境 包括java虚拟机和一些核心类库 核心类库主要是java lang包 ja
  • 准考证打印系统关闭怎么办_自考准考证错过打印时间,怎么办?

    点击上方蓝色字关注我们 后台回复 学历 1 5年快速拿正规名校学历 后台回复 优惠 2000元轻松入学升专本 后台回复 冲刺 获取自考备考冲刺模拟卷 后台回复 突击 0元抢占考前突击营名额 1 准考证一般什么时候开始打印 答 自学考试准考证
  • nginx php 错误日志,nginx、php-fpm、php 错误日志的关系

    nginx php fpm php 三者的配置文件中都有 error log 项 指定各自错误日志的保存路径 理论上它们三者的错误应该不会重合 即 nginx error log 记录的是 nginx 进程自己的错误 php fpm err
  • Linux 帧缓冲子系统详解:LCD介绍、framebuffer驱动框架、LCD驱动源码分析

    1 LCD显示屏基础知识介绍 请看博客 嵌入式开发 S5PV210 LCD显示器 2 内核帧缓冲子系统 2 1 功能介绍 1 帧缓冲 framebuffer 是 Linux 为显示设备提供的一个接口 它把显示设备描述成一个缓冲 区 允许应用
  • 简单理解 进程 & 线程

    文章目录 线程与进程之间的区别和联系 进程 线程之间的理解 进程 进程管理 PCB 并行 并发 线程 线程与进程之间的区别和联系 进程包含线程 都是为了实现并发编程的方式 线程比进程更轻量 进程是系统分配资源的基本单位 线程是系统调度执行的
  • python:Numpy学习(二)切片合集

    前言 本文根据本人自己的学习成果总结的 内容难免产生纰漏 如有错误 望各位路过大佬指出 建议按顺序食用本文 效果更佳 文内例子均以二维数组为例 本文主要包含numpy ndarray数组的多种切片方法 在阅读本文前 请思考下面的问题 Q 假
  • 大一自学Java到毕业,学会这些内容,就可以进大厂

    我就是自学Java进的大厂 学校很普通一个不知名的二本 专业是计算机专业 不过在学校学不到什么 基本都是靠自学 我们班进一线大厂的人有6个 我就是其中一个 剩下的人大部分去考研了 下面这个学习安排就是我在大学自学的内容 就适合时间多的大学生
  • 动手学CV-目标检测入门教程6:训练与测试

    3 6 训练与测试 本文来自开源组织 DataWhale CV小组创作的目标检测入门教程 对应开源项目 动手学CV Pytorch 的第3章的内容 教程中涉及的代码也可以在项目中找到 后续会持续更新更多的优质内容 欢迎 如果使用我们教程的内
  • 《软件方法》书中自测题大全-题目全文+分卷自测

    已经根据最新版本内容更新了在线题库 以下是 软件方法 1 8章中的自测题 答案不直接给出 可访问每套题后面的自测链接或扫二维码自测 做到全对才能知道答案 知识点见 软件方法 http www umlchina com book softme
  • Latex 字母上方箭头

    字母上方右箭头 mathop A limits rightarrow A mathop A limits rightarrow A 或者 vec A
  • 一款使用 Jetbrains IDE 开发事半功倍的工具

    使用 Jetbrains 公司开发软件的小伙伴一般都用 Toolbox App 来管理自己的开发软件 这个管理工具使用起来非常舒服 包括安装 更新 还等随心所欲的回滚和降级 这大大节省了维护IDE的时间和精力 IDE 管理 随心打开任意项目
  • c++类成员初始化方式

    转载自 https blog csdn net coder xia article details 7447822 常用的初始化可能如下 1 赋值初始化 class Student public Student string in name
  • 一个主设备号是如何支持多个次设备?

    1 主次设备号 参考博客 字符设备驱动详解 主次设备号 注册 卸载字符设备驱动 创建设备节点 地址映射 2 次设备号介绍 1 在老的驱动程序里是不需要次设备号的 在老版内核中注册驱动用register chrdev 函数 只需要传入主设备号
  • 自旋锁(spinlock) 解释得经典,透彻

    自旋锁与互斥锁有点类似 只是自旋锁不会引起调用者睡眠 如果自旋锁已经被别的执行单元保持 调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁 自旋 一词就是因此而得名 由于自旋锁使用者一般保持锁时间非常短 因此选择自旋而不是睡眠是非常必
  • 解决提示“Warning File ‘CMakeFilesxxxxxx.dirprogress.make‘ has modification time 2.4 s in the future”方法

    问题描述 今天分享一个我自己之前在使用虚拟机中使用cmake进行编译连接时候产生的一个告警提示 首先看告警提示 Warning File CMakeFiles xxxxxx dir progress make has modificatio
  • SMT HT CMP SMP

    1 多线程 同时多线程 Simultaneous multithreading 简称 SMT SMT 可通过复制处理器上的结构状态 让同一个处理器上的多个线程同步执行并共享处理器的执行资源 可最大限度地实现宽发射 乱序的超标量处理 提高处理
  • 多版本node的安装与切换详细操作

    多版本node的安装与切换详细操作 安装多版本node的原因 方法一 利用nvm进行管理 NVM 简介 安装前须知 卸载已安装的nodeJS nvm 的安装与使用 node 的不同版本安装及切换 方法二 通过配置环境变量 切换node时只需
  • Spark课程设计——电影推荐系统

    题目所需数据集及相应信息描述 数据集 1 用户评分数据集ratings dat 包含了大量用户的历史评分数据 2 样本评分数据集personalRatings dat 包含了少数几个用户的个性化评分数据 这些数据反映了某个用户的个性化观影喜