【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    Adventure
         1    Animation
         2     Children
         3       Comedy
         4      Fantasy
2        0    Adventure
         1     Children
         2      Fantasy
3        0       Comedy
         1      Romance
4        0       Comedy
         1        Drama
         2      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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis——缓存设计与优化

讲解Redis的缓存设计与优化&#xff0c;以及在生产环境中遇到的Redis常见问题&#xff0c;例如缓存雪崩和缓存穿透&#xff0c;还讲解了相关问题的解决方案。 1、Redis缓存的优点和缺点 1.1、缓存优点&#xff1a; 高速读写&#xff1a;Redis可以帮助解决由于数据库压力造成…

Blender教程(基础)-顶点的移动、滑移-16

一、顶点的移动与缩放 ShiftA新建柱体、切换到编辑模式 点模式下&#xff0c;选择一个顶点、选择移动&#xff08;GZ&#xff09;&#xff0c;发现顶点严Z轴移动&#xff0c;如下图所示 GY 按数字键盘7切换视图&#xff0c;选择这个面的所有顶点 按S把面缩放大 Ctrl…

第九个知识点:内部对象

Date对象: <script>var date new Date();date.getFullYear();//年date.getMonth();//月date.getDate();//日date.getDay();//星期几date.getHours();//时date.getMinutes();//分date.getSeconds();//秒date.getTime();//获取时间戳&#xff0c;时间戳时全球统一&#x…

一键放置柱子护角,你get了吗?

今天写个番外篇&#xff0c;给柱子添加护角。 记得几年前刚开始做BIM的时候&#xff0c;有次做车库导视方案模型&#xff0c;记得好像是鼎伦设计的车库一体化方案&#xff0c;当时柱子护角就给了两种方案&#xff0c;而且基本上每颗柱子上都要放护角&#xff0c;然后甲方竟然要…

容斥原理基础

文章目录 容斥原理的引入从集合的角度考虑推广例子不被2、3、5整除的数错排问题求不定方程的解Devu和鲜花 容斥原理的引入 从一个小学奥数问题引入&#xff1a; 一个班级有50人 喜欢语文的人有20人 喜欢数学的人有30人 同时喜欢语文数学的人有10人。 问题&#xff1a; 两门都不…

10个简单有效的编辑PDF文件工具分享

10个编辑PDF文件工具作为作家、编辑或专业人士&#xff0c;您可能经常发现自己在处理 PDF 文件。无论您是审阅文档、创建报告还是与他人共享工作&#xff0c;拥有一个可靠的 PDF 编辑器供您使用都非常重要。 10个简单适用的编辑PDF文件工具 在本文中&#xff0c;我们将介绍当今…

详细分析python中的 async 和 await(附Demo)

目录 前言1. 基本知识2. Demo2.1 Demo1&#xff08;同步&#xff09;2.2 Demo2&#xff08;错误&#xff09;2.3 Demo3&#xff08;不正确的异步&#xff09;2.4 Demo4&#xff08;正确异步&#xff09; 3. 完整版4. 拓展4.1 asyncio.create_task(coroutine)4.2 asyncio.gather…

FXTM富拓监管变更!2024开年连续3家交易商注销牌照

交易商的监管信息是经常发生变更的&#xff0c;即使第一次投资时查询平台监管牌照&#xff0c;投资者仍需持续关注其监管动态。千万不要以为第一步审核好后就万事大吉了&#xff01; 2024年开年&#xff0c;就有3家交易商的重要信息发生变更&#xff0c;注销其金融监管牌照&…

Java 将TXT文本文件转换为PDF文件

与TXT文本文件&#xff0c;PDF文件更加专业也更适合传输&#xff0c;常用于正式报告、简历、合同等场合。项目中如果有使用Java将TXT文本文件转为PDF文件的需求&#xff0c;可以查看本文中介绍的免费实现方法。 免费Java PDF库 本文介绍的方法需要用到Free Spire.PDF for Java…

编程实例分享,宠物诊所电子处方怎么开,兽医电子处方模板电子版操作教程

编程实例分享&#xff0c;宠物诊所电子处方怎么开&#xff0c;兽医电子处方模板电子版操作教程 一、前言 以下操作教程以 佳易王兽医电子处方软件V16.0为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、在系统 设置里可以设置打印参数&#x…

《动手学深度学习(PyTorch版)》笔记7.2

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过&…

单片机学习笔记---LED点阵屏的工作原理

目录 LED点阵屏分类 LED点阵屏显示原理 74HC595的介绍 一片74HC595的工作原理 多片级联工作原理 总结 LED点阵屏由若干个独立的LED组成&#xff0c;LED以矩阵的形式排列&#xff0c;以灯珠亮灭来显示文字、图片、视频等。LED点阵屏广泛应用于各种公共场合&#xff0c;如汽…

go语言进阶篇——面向对象(一)

什么是面向对象 在我们设计代码时&#xff0c;比如写一个算法题或者写一个问题结局办法时&#xff0c;我们常常会使用面向过程的方式来书写代码&#xff0c;面向过程主要指的是以解决问题为中心&#xff0c;按照一步步具体的步骤来编写代码或者调用函数&#xff0c;他在问题规…

后端创建订单

package com.java1234.entity;import io.jsonwebtoken.Claims;/*** jwt验证信息* author java1234_小锋* site www.java1234.com* company Java知识分享网* create 2019-08-13 上午 10:00*/ public class CheckResult {private int errCode;private boolean success;private Cl…

Linux下的多线程

前面学习了进程、文件等概念&#xff0c;接下里为大家引入线程的概念 多线程 线程是什么&#xff1f;为什么要有线程&#xff1f;线程的优缺点Linux线程操作线程创建线程等待线程终止线程分离 线程间的私有和共享数据理解线程库和线程id深刻理解Linux多线程&#xff08;重点&a…

2023年全国职业院校技能大赛软件测试赛题第3套

2023年全国职业院校技能大赛 软件测试赛题第3套 赛项名称&#xff1a; 软件测试 英文名称&#xff1a; Software Testing 赛项编号&#xff1a; GZ034 归属产业&#xff1a; 电子与信息大类 …

软件价值10-数字时钟

这是一个数字时钟程序&#xff1a; # importing whole module from tkinter import * from tkinter.ttk import *# importing strftime function to # retrieve systems time from time import strftime# creating tkinter window root Tk() root.title(Clock)# This functio…

Docker Compose实例

目录 一、前提说明 二、简单的Docker容器部署案例 1. Dockerfile 配置 2. docker-compose.yml 配置 3. application.properties 配置 4. pom.xml 配置 5. 上传文件 6. 创建基础Docker镜像 7. docker-compose.yml编排 8. 停止并删除容器编排 一、前提说明 在配置好Do…

【博云2023】乘龙一跃腾云海,侧目抬手摘星河

癸卯渐远&#xff0c;甲辰渐至&#xff0c;预示着被汗水浇灌的种子&#xff0c;必将顶开冻土&#xff0c;迎接阳光。 每逢春节&#xff0c;当亲友彼此问候&#xff0c;博云人总能自豪地说&#xff0c;我们认真地、努力地奋斗&#xff0c;让我们能自信地踏上新的征程。 我们的…

使用Python进行数据的描述性分析,用少量的描述性指标来概括大量的原始数据

在进行数据分析时&#xff0c;当研究者得到的数据量很小时&#xff0c;可以通过直接观察原始数据来获得所有的信息。但是&#xff0c;当得到的数据量很大时&#xff0c;就必须借助各种描述性指标来完成对数据的描述工作。用少量的描述性指标来概括大量的原始数据&#xff0c;对…