【Python基础】案例分析:电影分析

电影分析

项目背景:

  • 数据集介绍:movie_lens数据集是一个电影信息,电影评分的数据集,可以用来做推荐系统的数据集
  • 需求:对电影发展,类型,评分等做统计分析。
  • 目标:巩固pandas相关知识点

1 数据整理

1.1 熟悉数据据知识点

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
%matplotlib inline
mv_path = r'data\ml-latest-small\movies.csv'
rating_path = r'data\ml-latest-small\ratings.csv'
tags_path = r'data\ml-latest-small\tags.csv'
df_mv = pd.read_csv(mv_path)
df_rating = pd.read_csv(rating_path)
df_tags = pd.read_csv(tags_path)
df_mv.head()
movieIdtitlegenres
01Toy Story (1995)Adventure|Animation|Children|Comedy|Fantasy
12Jumanji (1995)Adventure|Children|Fantasy
23Grumpier Old Men (1995)Comedy|Romance
34Waiting to Exhale (1995)Comedy|Drama|Romance
45Father of the Bride Part II (1995)Comedy
df_rating.head()
userIdmovieIdratingtimestamp
0114.0964982703
1134.0964981247
2164.0964982224
31475.0964983815
41505.0964982931
df_tags.head()
userIdmovieIdtagtimestamp
0260756funny1445714994
1260756Highly quotable1445714996
2260756will ferrell1445714992
3289774Boxing story1445715207
4289774MMA1445715200

1.2 缺省值判断

dfs = [df_mv, df_rating, df_tags]
for df in dfs:print(df.columns.values)print(df.isnull().sum())print('======')
['movieId' 'title' 'genres']
movieId    0
title      0
genres     0
dtype: int64
======
['userId' 'movieId' 'rating' 'timestamp']
userId       0
movieId      0
rating       0
timestamp    0
dtype: int64
======
['userId' 'movieId' 'tag' 'timestamp']
userId       0
movieId      0
tag          0
timestamp    0
dtype: int64
======

2 电影分析

分析目标:

  • 电影数量
  • 电影题材数量
  • 电影年代
  • 标签,评分

2.1 数量

df_mv.movieId.size
9742

2.2 题材分析

  • 查看genres字段
df_mv.head()
movieIdtitlegenres
01Toy Story (1995)Adventure|Animation|Children|Comedy|Fantasy
12Jumanji (1995)Adventure|Children|Fantasy
23Grumpier Old Men (1995)Comedy|Romance
34Waiting to Exhale (1995)Comedy|Drama|Romance
45Father of the Bride Part II (1995)Comedy

2.3 genres拆分

#设置movieId为索引
#使用前4行练习,
#切分字符串,
#行列转换
tmp = df_mv.set_index('movieId')[:4].genres.str.split('|', expand=True)
tmp
01234
movieId
1AdventureAnimationChildrenComedyFantasy
2AdventureChildrenFantasyNoneNone
3ComedyRomanceNoneNoneNone
4ComedyDramaRomanceNoneNone
t = tmp.stack()
t
movieId   
1        0    Adventure1    Animation2     Children3       Comedy4      Fantasy
2        0    Adventure1     Children2      Fantasy
3        0       Comedy1      Romance
4        0       Comedy1        Drama2      Romance
dtype: object
df_genres = t.droplevel(1)
df_genres
movieId
1    Adventure
1    Animation
1     Children
1       Comedy
1      Fantasy
2    Adventure
2     Children
2      Fantasy
3       Comedy
3      Romance
4       Comedy
4        Drama
4      Romance
dtype: object
# 代码整理
tmp = df_mv.set_index('movieId').genres.str.split('|', expand=True)
t = tmp.stack()
df_genres = tmp.stack().droplevel(1)
df_genres
movieId
1         Adventure
1         Animation
1          Children
1            Comedy
1           Fantasy...    
193583      Fantasy
193585        Drama
193587       Action
193587    Animation
193609       Comedy
Length: 22084, dtype: object
# 查看题材分布
genres = df_genres.value_counts()
genres
Drama                 4361
Comedy                3756
Thriller              1894
Action                1828
Romance               1596
Adventure             1263
Crime                 1199
Sci-Fi                 980
Horror                 978
Fantasy                779
Children               664
Animation              611
Mystery                573
Documentary            440
War                    382
Musical                334
Western                167
IMAX                   158
Film-Noir               87
(no genres listed)      34
Name: count, dtype: int64
#列重命名
genres = genres.reset_index().rename({'index':'genres',0:'count'}, axis=1)
genres
genrescount
0Drama4361
1Comedy3756
2Thriller1894
3Action1828
4Romance1596
5Adventure1263
6Crime1199
7Sci-Fi980
8Horror978
9Fantasy779
10Children664
11Animation611
12Mystery573
13Documentary440
14War382
15Musical334
16Western167
17IMAX158
18Film-Noir87
19(no genres listed)34
#设置图标格式
plt.figure(figsize=(16,5))
ax = sns.barplot(x='genres', y = 'count', data=genres)
_ = ax.set_xticklabels(ax.get_xticklabels(), rotation=70)
UserWarning: FixedFormatter should only be used together with FixedLocator_ = ax.set_xticklabels(ax.get_xticklabels(), rotation=70)

在这里插入图片描述

2.4 电影年代

  • 数据:

title字段中,含有年代,使用正则表达式提取

  • 目标

每个年份电影

每个年份电影题材份电影题材

t = df_mv.set_index('movieId').title
df_year = t.str.extract(r'\((\d+)\)')
#统计没有年份的电影
df_year.isnull().sum()
0    13
dtype: int64
#删除没有年份电影
year_data = df_year.dropna()
#将数据整理成DataFrame对象
year_data = year_data.reset_index().rename({0:'year'}, axis=1)
year_data.head()
movieIdyear
011995
121995
231995
341995
451995
# 检查数据
# 提取年份是否正确?
year_data.year.agg(['max', 'min'])
max    500
min     06
Name: year, dtype: object
# 找出异常数据
tmp = year_data[year_data.year.isin(['06','500'])]
tmp
movieIdyear
67488906
707469757500
#找出异常原始数据
t = df_mv[df_mv.movieId.isin(tmp.movieId)]
t
movieIdtitlegenres
6748891-900 (06) (1994)Drama|Romance
707569757(500) Days of Summer (2009)Comedy|Drama|Romance
# 问题:提取数据方式没问题,但是数据不规范,提取其他值
# 解决方式:修改正则表达式
t.title.str.extract(r'\((\d+)\)$')
0
6741994
70752009
# 重新提取数据
t = df_mv.set_index('movieId').title
df_year = t.str.extract(r'\((\d+)\)$')
#删除没有年份电影
year_data = df_year.dropna()
#将数据整理成DataFrame对象
year_data = year_data.reset_index().rename({0:'year'}, axis=1)
#获取最大最小值
year_data.year.agg(['max', 'min'])
max    2018
min    1902
Name: year, dtype: object
year_data = year_data.sort_values('year')
year_data
movieIdyear
5867328981902
6353493891903
90081405411908
474370651915
81611027471916
.........
96841875412018
96851875932018
96861875952018
96721849312018
96541832952018

9718 rows × 2 columns

# 按年份进行统计
#设置图标格式
plt.figure(figsize=(20,5))
ax = sns.countplot(x='year', data=year_data)
_ = ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
 UserWarning: FixedFormatter should only be used together with FixedLocator_ = ax.set_xticklabels(ax.get_xticklabels(), rotation=90)

在这里插入图片描述

#设年份大与1970
plt.figure(figsize=(15,5))
ax = sns.countplot(x='year', data=year_data[year_data.year>'1970'])
_ = ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
UserWarning: FixedFormatter should only be used together with FixedLocator_ = ax.set_xticklabels(ax.get_xticklabels(), rotation=90)

在这里插入图片描述

2.5 年代与题材

1990年后:每年不同题材电影数量

year_data.head()
movieIdyear
5867328981902
6353493891903
90081405411908
474370651915
81611027471916
#df_genres处理
genres_data = df_genres.reset_index().rename({0:'genres'},axis=1)
genres_data.head()
movieIdgenres
01Adventure
11Animation
21Children
31Comedy
41Fantasy
#提取部分数据进行megre
d1 = year_data[:2]
d2 = genres_data[:10]
d1
movieIdyear
5867328981902
6353493891903
d2
movieIdgenres
01Adventure
11Animation
21Children
31Comedy
41Fantasy
52Adventure
62Children
72Fantasy
83Comedy
93Romance
#实际数据合并,只处理1990年以后数据
ydata = year_data[year_data.year>='1990']
ygdata = ydata.merge(genres_data)
ygdata.year.unique()
array(['1990', '1991', '1992', '1993', '1994', '1995', '1996', '1997','1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005','2006', '2007', '2008', '2009', '2010', '2011', '2012', '2013','2014', '2015', '2016', '2017', '2018'], dtype=object)
# 绘制柱状图
plt.figure(figsize=(100,5))
ax = sns.countplot(x='year', data=ygdata, hue="genres", orient='v')
_ = ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
 UserWarning: FixedFormatter should only be used together with FixedLocator_ = ax.set_xticklabels(ax.get_xticklabels(), rotation=90)

在这里插入图片描述

# 绘制线形图
import numpy as np
ygdata['num']=np.ones_like(ygdata.year)
plt.figure(figsize=(20,5))
ax = sns.lineplot(x='year',y='num', data=ygdata, hue="genres", estimator='sum')


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

df_rating.head()
userIdmovieIdratingtimestamp
0114.0964982703
1134.0964981247
2164.0964982224
31475.0964983815
41505.0964982931

3 评分分析

  • 每年评价数量
  • 小时评价数量
  • 月评价数量
  • 电影评分数量
  • 电影评分排名TOPN

3.1 时间分析

  • 时间戳转时间
  • 获取年月小时
    获取年月小时
ts = pd.to_datetime(df_rating.timestamp.values, unit='s')
df_rating['times'] = ts
df_rating['day'] = ts.to_period('D')
df_rating['month'] = ts.map(lambda x:x.month)
df_rating['year'] = ts.to_period('Y')
df_rating['hour'] = ts.map(lambda x:x.hour)
df_rating.head()
userIdmovieIdratingtimestamptimesdaymonthyearhour
0114.09649827032000-07-30 18:45:032000-07-307200018
1134.09649812472000-07-30 18:20:472000-07-307200018
2164.09649822242000-07-30 18:37:042000-07-307200018
31475.09649838152000-07-30 19:03:352000-07-307200019
41505.09649829312000-07-30 18:48:512000-07-307200018
ax = sns.countplot(x='year', data=df_rating, order=sorted(df_rating.year.unique()))
_ = ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
 UserWarning: FixedFormatter should only be used together with FixedLocator_ = ax.set_xticklabels(ax.get_xticklabels(), rotation=90)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

sorted(df_rating.year.unique())
[Period('1996', 'A-DEC'),Period('1997', 'A-DEC'),Period('1998', 'A-DEC'),Period('1999', 'A-DEC'),Period('2000', 'A-DEC'),Period('2001', 'A-DEC'),Period('2002', 'A-DEC'),Period('2003', 'A-DEC'),Period('2004', 'A-DEC'),Period('2005', 'A-DEC'),Period('2006', 'A-DEC'),Period('2007', 'A-DEC'),Period('2008', 'A-DEC'),Period('2009', 'A-DEC'),Period('2010', 'A-DEC'),Period('2011', 'A-DEC'),Period('2012', 'A-DEC'),Period('2013', 'A-DEC'),Period('2014', 'A-DEC'),Period('2015', 'A-DEC'),Period('2016', 'A-DEC'),Period('2017', 'A-DEC'),Period('2018', 'A-DEC')]

3.2 电影评分

3.2.1 评价数量前10

#根据movieId分组,统计数量
tmp = df_rating.groupby('movieId').year.count()
#排序,取前10
tmp.sort_values(ascending=False)[:10]
movieId
356     329
318     317
296     307
593     279
2571    278
260     251
480     238
110     237
589     224
527     220
Name: year, dtype: int64
tmp = df_rating.groupby('movieId').rating.mean()
tmp
movieId
1         3.920930
2         3.431818
3         3.259615
4         2.357143
5         3.071429...   
193581    4.000000
193583    3.500000
193585    3.500000
193587    3.500000
193609    4.000000
Name: rating, Length: 9724, dtype: float64
#根据movieId分组,统计数量大于10
tmp = df_rating.groupby('movieId')['rating'].apply(lambda x: 0 if x.size <10 else x.mean())
#排序,取前10
tmp.sort_values(ascending=False)[:10]
movieId
1041    4.590909
3451    4.545455
1178    4.541667
1104    4.475000
2360    4.458333
1217    4.433333
318     4.429022
951     4.392857
1927    4.350000
922     4.333333
Name: rating, dtype: float64

3.3 用户喜好

  • 用户打标签
  • 思路:根据用户评分与电影题材,为用户打标签

1:获取某个用户评分所有电影

2:获取评分电影对应题材

3:统计题材数量并排序

mvids = df_rating[df_rating.userId == 1].movieId
t = genres_data[genres_data.movieId.isin(mvids)].genres.value_counts()
t
genres
Action       90
Adventure    85
Comedy       83
Drama        68
Thriller     55
Fantasy      47
Crime        45
Children     42
Sci-Fi       40
Animation    29
Romance      26
War          22
Musical      22
Mystery      18
Horror       17
Western       7
Film-Noir     1
Name: count, dtype: int64

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2774093.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

《幻兽帕鲁》攻略:0基础入门及游戏基础操作 幻兽帕鲁基础设施 幻兽帕鲁基础攻击力 Mac苹果电脑玩幻兽帕鲁 幻兽帕鲁加班加点

今天就跟大家聊聊《幻兽帕鲁》攻略&#xff1a;0基础入门及游戏基础操作。 如果想在苹果电脑玩《幻兽帕鲁》记得安装CrossOver哦。 以下纯干货&#xff1a; CrossOver正版安装包&#xff08;免费试用&#xff09;&#xff1a;https://souurl.cn/Y1gDao 一、基础操作 二、界面…

加固平板电脑丨三防智能平板丨工业加固平板丨智能城市管理

随着智能城市的不断发展&#xff0c;人们对于城市管理的要求也在不断提高&#xff0c;这就需要高效、智能的城市管理平台来实现。而三防平板就是一款可以满足这一需求的智能设备。 三防平板是一种集防水、防尘、防摔于一体的智能平板电脑&#xff0c;它可以在复杂的环境下稳定运…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之ScrollBar组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之ScrollBar组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、ScrollBar组件 鸿蒙&#xff08;HarmonyOS&#xff09;滚动条组件ScrollBar&…

Unity BuffSystem buff系统

Unity BuffSystem buff系统 一、介绍二、buff系统架构三、架构讲解四、框架使用buff数据Json数据以及工具ShowTypeBuffTypeMountTypeBuffOverlapBuffShutDownTypeBuffCalculateType时间和层数这里也不过多说明了如何给生物添加buff 五、总结 一、介绍 现在基本做游戏都会需要些…

pwn学习笔记(2)ret_2_text_or_shellcode

pwn学习笔记&#xff08;2&#xff09; 1.三种常见的寄存器&#xff1a; ​ ax寄存器&#xff1a;通用寄存器&#xff0c;可用于存放多种数据 ​ bp寄存器&#xff1a;存放的是栈帧的栈底地址 ​ sp寄存器&#xff1a;存放的是栈顶的地址 2.栈帧与栈工作的简介&#xff1a…

生态地板行业分析:营收入同比增长20%以上

绿色建材是在全生命周期内可减少对天然资源消耗和减轻对生态环境影响&#xff0c;本质更安全、使用更便利&#xff0c;具有“节能、减排、安全、便利和可循环”特征的建材。低碳环保概念已经逐渐渗透到各个行业中&#xff0c;地板行业也不例外。尤其是在环保税法实施后&#xf…

【RT-DETR有效改进】轻量级下采样方法ContextGuided(参数量下降700W,轻量又涨点)

&#x1f451;欢迎大家订阅本专栏&#xff0c;一起学习RT-DETR&#x1f451; 一、本文介绍 本文给大家带来的是改进机制是一种替换Conv的模块Context Guided Block (CG block) &#xff0c;其是在CGNet论文中提出的一种模块&#xff0c;其基本原理是模拟人类视觉系统依赖上…

人力资源智能化管理项目(day03:主页模块)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/humanResourceIntelligentManagementProject 觉得有帮助的同学&#xff0c;可以点心心支持一下哈 主页权限验证(permission.js) import router from /router import nprogress from nprogress // 进度条 import nprog…

Django模板(二)

标签if 标签在渲染过程中提供使用逻辑的方法,比如:if和for 标签被 {% 和 %} 包围,如下所示: 由于在模板中,没有办法通过代码缩进判断代码块,所以控制标签都需要有结束的标签 if判断标签{% if %} {% endif %} : # athlete_list 不为空 {% if athlete_list %}# 输出 ath…

Spring + Tomcat项目中nacos配置中文乱码问题解决

实际工作的时候碰到了nacos中文乱码的问题&#xff0c;一顿排查最终还是调源码解决了。下面为具体的源码流程&#xff0c;有碰到的可以参考下。 对于nacos配置来说&#xff0c;初始主要源码就在NacosConfigService类中。里面有初始化获取配置content以及设置对应监听器的操作。…

原生JS使用PrintJs进行表格打印 -- 遇到的问题总结

需求1&#xff1a;表格自动分页之后&#xff0c;表头在每一页都需要显示 html中表头增加 thead 标签 css样式新增&#xff1a; thead {display: table-header-group; /* 这个属性使thead总是在新的page-break之后重新开始 */ }需求2&#xff1a;表格自动分页之后&#xff0c;…

Springboot 整合 Elasticsearch(三):使用RestHighLevelClient操作ES ①

&#x1f4c1; 前情提要&#xff1a; Springboot 整合 Elasticsearch&#xff08;一&#xff09;&#xff1a;Linux下安装 Elasticsearch 8.x Springboot 整合 Elasticsearch&#xff08;二&#xff09;&#xff1a;使用HTTP请求来操作ES 目录 一、Springboot 整合 Elasticsea…

c++设计模式之装饰器模式

作用 为现有类增加功能 案例说明 class Car { public:virtual void show()0; };class Bmw:public Car { public:void show(){cout<<"宝马汽车>>"<<endl;} };class Audi:public Car { public:void show(){cout<<"奥迪汽车>>&q…

2023年12月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,共50分) 第1题 一个非零的二进制正整数,在其末尾添加两个“0”,则该新数将是原数的?( ) A:10倍 B:2倍 C:4倍 D:8倍 答案:C 二进制进位规则是逢二进一,因此末尾添加一个0,是扩大2倍,添加两个0…

【Linux开发工具】yum命令详解

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 1.概念2.yum的配置信…

Docker-Learn(二)保存、导入、使用Docker镜像

1.保存镜像 根据上一节内容&#xff0c;将创建好镜像进行保存&#xff0c;需要退出当前的已经在运行的docer命令行中断里面&#xff0c;可以通过在终端里面输入指令exit或者按下键盘上的 ctrlD建退出&#xff1a; 回到自己的终端里面&#xff0c;输入指令&#xff1a; docker…

学习VR全景拍摄,如何选择适合的VR全景设备?

随着VR全景技术的不断成熟和发展&#xff0c;VR全景已经成为摄影爱好者、地产行业、中介经纪人、广告、企业宣传等行业从业者们乐于尝试的新领域、新手段。 如何选择合适的VR全景设备成为了一个重要的问题。今天&#xff0c;和大家聊一聊&#xff0c;不同行业、人群和用途更适合…

从Unity到Three.js(安装启动)

发现在3D数字孪生或模拟仿真方向&#xff0c;越来越多的公司倾向使用Web端程序&#xff0c;目前一直都是使用的Unity进行的Web程序开发&#xff0c;但是存在不少问题&#xff0c;比如内存释放、shader差异化、UI控件不支持复制或输入中文等。虽然大多数问题都可以找到解决方案&…

Swift Combine 发布者publisher的生命周期 从入门到精通四

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三 1. 发布者和订阅者的生命周期 订阅者和发布者以明确定义的顺序进行通信&#xff0c;因此使得它们具有从开始到结束的生命周期&#xff1a; …

Leetcode3020. 子集中元素的最大数量

Every day a Leetcode 题目来源&#xff1a;3020. 子集中元素的最大数量 解法1&#xff1a;哈希 枚举 用一个哈希表统计数组 nums 中的元素及其出现次数。 暴力枚举数组中的数&#xff0c;作为 x&#xff0c;然后不断看 x2,x4,⋯ 在数组中的个数。直到个数不足 2 个为止&a…