【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://www.mzph.cn/news/674244.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Layui 表格组件 头部工具栏 筛选列 加入全选和全不选的功能

Layui 表格组件 头部工具栏 筛选列 加入全选和全不选的功能 问题 前端使用Layui表格组件展示后台数据&#xff0c;因数据中涉及字段较多&#xff0c;因此加入了组件中固有的控制表格列隐藏显示的功能。奈何客户希望再此基础上&#xff0c;加入“全选”和“全不选”的功能&…

【动态规划】【前缀和】【C++算法】LCP 57. 打地鼠

作者推荐 视频算法专题 本文涉及知识点 动态规划汇总 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 LCP 57. 打地鼠 勇者面前有一个大小为3*3 的打地鼠游戏机&#xff0c;地鼠将随机出现在各个位置&#xff0c;moles[i] [t,x,y] 表…

Stable Diffusion 模型下载:Samaritan 3d Cartoon SDXL(撒玛利亚人 3d 卡通 SDXL)

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 由“PromptSharingSamaritan”创作的撒玛利亚人 3d 卡通类型的大模型&#xff0c;该模型的基础模型为 SDXL 1.0。 条目内容类型大模型基础模型SDXL 1.0来源CIVITA…

2024.2.7

#include<stdio.h> #include<string.h> #include<stdlib.h> typedef char datatype;typedef struct node {//数据域datatype data;//指针域&#xff1a;左struct node *lchild;//指针域&#xff1a;右struct node *rchild; }*btree;//创建节点 btree creat_n…

嵌入式中轻松识别STM32单片机是否跑飞方法

单片机项目偶尔经常出现异常&#xff0c;不知道是程序跑飞了&#xff0c;还是进入某个死循环了&#xff1f; 因为发生概率比较低&#xff0c;也没有规律&#xff0c;所以没办法在线调试查找问题。 结合这个问题&#xff0c;给大家分享一下用ST-LINK Utility识别单片机程序是否…

python-可视化篇-pyecharts库-气候堆叠图

准备 代码 # codingutf-8 # 代码文件&#xff1a;code/chapter10/10.3.py # 3D柱状图import randomfrom pyecharts import options as opts from pyecharts.charts import Bar3D# 生成测试数据 data [[x, y, random.randint(10, 40)] for y in range(7) for x in range(24)]…

Git中为常用指令配置别名

目录 1 前言 2 具体操作 2.1 创建.bashrc文件 2.2 添加指令 2.3 使其生效 2.4 测试 1 前言 在Git中有一些常用指令比较长&#xff0c;当我们直接输入&#xff0c;不仅费时费力&#xff0c;还容易出错。这时候&#xff0c;如果能给其取个简短的别名&#xff0c;那么事情就…

电力负荷预测 | 电力系统负荷预测模型(Python线性回归、随机森林、支持向量机、BP神经网络、GRU、LSTM)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 电力系统负荷预测模型(Python线性回归、随机森林、支持向量机、BP神经网络、GRU、LSTM) 所谓预测,就是指通过对事物进行分析及研究,并运用合理的方法探索事物的发展变化规律,对其未来发展做出预先估计和判断。…

计算机毕业设计 | SSM 医药信息管理系统(附源码)

1&#xff0c; 概述 1.1 课题背景 本系统由说书客面向广大民营药店、县区级医院、个体诊所等群体的药品和客户等信息的管理需求&#xff0c;采用SpringSpringMVCMybatisEasyui架构实现&#xff0c;为单体药店、批发企业、零售连锁企业&#xff0c;提供有针对性的信息数据管理…

MySQL 时间索引的选择

背景 MySQL 在使用过程中经常会对时间加索引&#xff0c;方便进行时间范围的查询&#xff0c;常见的时间类型有 data、datetime、long、timestamp 等&#xff0c;在此分析下这几种时间类型的索引大小&#xff0c;以找到比较合适的时间类型。 时间类型对比 常用的索引类型是 …

HttpServletResponse接口用于表示状态代码的字段

1. HttpServletResponse接口用于表示状态代码的字段 您已学习了状态代码以及可用于从servlet向客户机发送状态代码的HttpServletResponse接口的字段。下表列出了HttpServletResponse接口表示状态代码的一些其他字段。 字段状态代码描述SC_HTTP_VERSION_NOT_SUPPORTED505服务器…

PyTorch深度学习实战(23)——从零开始实现SSD目标检测

PyTorch深度学习实战&#xff08;23&#xff09;——从零开始实现SSD目标检测 0. 前言1. SSD 目标检测模型1.1 SSD 网络架构1.2 利用不同网络层执行边界框和类别预测1.3 不同网络层中默认框的尺寸和宽高比1.4 数据准备1.5 模型训练 2. 实现 SSD 目标检测2.1 SSD300 架构2.2 Mul…

Verilog刷题笔记25

题目&#xff1a; You’re already familiar with bitwise operations between two values, e.g., a & b or a ^ b. Sometimes, you want to create a wide gate that operates on all of the bits of one vector, like (a[0] & a[1] & a[2] & a[3] … ), whic…

USB Type-C 接口 PD 协议解决方案

文章来源&#xff1a;USB Type-C接口PD协议解决方案 | Richtek Technology

极值图论基础

目录 一&#xff0c;普通子图禁图 二&#xff0c;Turan问题 三&#xff0c;Turan定理、Turan图 1&#xff0c;Turan定理 2&#xff0c;Turan图 四&#xff0c;以完全二部图为禁图的Turan问题 1&#xff0c;最大边数的上界 2&#xff0c;最大边数的下界 五&#xff0c;…

【C++基础入门】七、指针(定义和使用、所占内存空间、空指针和野指针、const关键字修饰指针、指针和数组、指针和函数)

七、指针 7.1 指针的基本概念 指针的作用&#xff1a; 可以通过指针间接访问内存 内存编号是从0开始记录的&#xff0c;一般用十六进制数字表示可以利用指针变量保存地址 7.2 指针变量的定义和使用 指针变量定义语法&#xff1a; 数据类型 * 变量名&#xff1b; 示例&…

DevOps落地笔记-21|业务价值:软件发布的最终目的

上一课时介绍如何度量软件的内部质量和外部质量。在外部质量中&#xff0c;我们提到用户满意度是衡量软件外部质量的关键因素。“敏捷宣言”的第一条原则规定&#xff1a;“我们最重要的目标&#xff0c;是通过持续不断的及早交付有价值的软件使用户满意”。从这一点也可以看出…

2024.2.6

1.现有无序序列数组为23,24,12,5,33,5347&#xff0c;请使用以下排序实现编程 函数1:请使用冒泡排序实现升序排序 函数2:请使用简单选择排序实现升序排序 函数3:请使用快速排序实现升序排序 函数4:请使用插入排序实现升序排序 #include<stdio.h> #include<string.h&g…

简化版SpringMVC

简化版SpringMVC web.xml xml version"1.0" encoding"UTF-8"?> <web-app version"2.5" xmlns"http://java.sun.com/xml/ns/javaee" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation&quo…

【制作100个unity游戏之24】unity制作一个3D动物AI生态系统游戏2(附项目源码)

最终效果 文章目录 最终效果系列目录前言添加捕食者动画控制源码完结 系列目录 前言 欢迎来到【制作100个Unity游戏】系列&#xff01;本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第24篇中&#xff0c;我们将探索如何用unity制作一个3D动物AI生态系统游戏…