当前位置: 首页 > news >正文

Python数据分析:整理Netflix演员电影评分项目实战

Netflix数据揭秘:谁是各流派评分之王?🎬

大家好!最近我完成了一个有趣的数据分析实战项目——整理Netflix电影和电视剧的演员评分数据,最终挖掘出各个流派中平均IMDB评分最高的演员。今天我就严格按照项目笔记的流程,把完整的数据清洗、整理、分析过程分享给大家,希望能给同样对数据感兴趣的小伙伴一些启发!


📌 分析目标

此数据分析的目的是,整理不同流派影视作品(比如喜剧片、动作片、科幻片)中,各演员出演作品的平均IMDB评分,从而挖掘出各个流派中的高评分作品演员。本实战项目的目的在于练习整理数据,从而得到可供下一步分析的数据。

📁 数据集简介

原始数据集记录了截止至2022年7月美国地区可观看的所有Netflix电视剧及电影数据。数据集包含两个数据表:titles.csvcredits.csv

titles.csv包含电影及电视剧相关信息,每列含义如下:

  • id:影视作品ID

  • title:影视作品标题

  • type:作品类型(电视节目SHOW或电影MOVIE)

  • description:简短描述

  • release_year:发布年份

  • age_certification:适龄认证

  • runtime:每集或电影的长度(分钟)

  • genres:流派类型列表(字符串形式的列表)

  • production_countries:出品国家列表(字符串形式的列表)

  • seasons:如果是电视剧,则是季数

  • imdb_id:IMDB的ID

  • imdb_score:IMDB评分

  • imdb_votes:IMDB投票数

  • tmdb_popularity:TMDB流行度

  • tmdb_score:TMDB评分

credits.csv包含演职员信息,每列含义如下:

  • person_id:演职员ID

  • id:参与的影视作品ID

  • name:姓名

  • character:角色姓名

  • role:演职员类型(ACTOR演员或DIRECTOR导演)


📥 读取数据

首先导入数据分析所需的库——Pandas,并通过read_csv函数将两个原始数据文件读入DataFrame。

import pandas as pd original_titles = pd.read_csv("titles.csv") original_credits = pd.read_csv("credits.csv")

查看前几行数据,确认读取成功:

original_titles.head()

id

title

type

description

release_year

age_certification

runtime

genres

production_countries

seasons

imdb_id

imdb_score

imdb_votes

tmdb_popularity

tmdb_score

ts300399

Five Came Back: The Reference...

SHOW

This collection includes 12 World War II-era p...

1945

TV-MA

51

['documentation']

['US']

1.0

NaN

NaN

NaN

0.600

NaN

tm84618

Taxi Driver

MOVIE

A mentally unstable Vietnam War veteran works ...

1976

R

114

['drama', 'crime']

['US']

NaN

tt0075314

8.2

808582.0

40.965

8.179

tm154986

Deliverance

MOVIE

Intent on seeing the Cahulawassee River before...

1972

R

109

['drama', 'action', 'thriller', 'european']

['US']

NaN

tt0068473

7.7

107673.0

10.010

7.300

tm127384

Monty Python and the Holy Grail

MOVIE

King Arthur, accompanied by his squire, recrui...

1975

PG

91

['fantasy', 'action', 'comedy']

['GB']

NaN

tt0071853

8.2

534486.0

15.461

7.811

tm120801

The Dirty Dozen

MOVIE

12 American military prisoners in World War II...

1967

NaN

150

['war', 'action']

['GB', 'US']

NaN

tt0061578

7.7

72662.0

20.398

7.600

original_credits.head()

person_id

id

name

character

role

3748

tm84618

Robert De Niro

Travis Bickle

ACTOR

14658

tm84618

Jodie Foster

Iris Steensma

ACTOR

7064

tm84618

Albert Brooks

Tom

ACTOR

3739

tm84618

Harvey Keitel

Matthew 'Sport' Higgins

ACTOR

48933

tm84618

Cybill Shepherd

Betsy

ACTOR


🧹 评估和清理数据

为了区分原始数据和清洗后的数据,我们先创建两个副本:

cleaned_titles = original_titles.copy() cleaned_credits = original_credits.copy()

📐 数据整齐度

cleaned_titles的前10行可以看出,genresproduction_countries列中包含多个值(以列表形式存储),但实际上它们是字符串,需要拆分成多行。

查看genres列的第一个值:

cleaned_titles['genres'][1]

输出:"['drama', 'crime']"(字符串)

使用eval函数将字符串转换为真正的列表:

cleaned_titles['genres'] = cleaned_titles['genres'].apply(lambda s: eval(s)) cleaned_titles['genres'][1]

输出:['drama', 'crime'](列表)

然后用explode将列表拆成多行:

cleaned_titles = cleaned_titles.explode("genres") cleaned_titles.head(10)

(此处显示拆分行后的结果,原本一行变成多行)

同样的操作也应用于production_countries列:

cleaned_titles['production_countries'] = cleaned_titles['production_countries'].apply(lambda s: eval(s)) cleaned_titles = cleaned_titles.explode('production_countries')

查看cleaned_credits的前10行,结构已经很整齐,无需进一步拆分。


🧼 数据干净度

通过info()了解数据的基本情况:

cleaned_titles.info()

输出显示共有17818条记录,多个列存在缺失值,如title(缺失1条)、description(缺失28条)、age_certification(缺失较多)、genres(缺失63条)、production_countries(缺失379条)、seasons(缺失很多)、imdb_score(缺失842条)等。

另外,release_year是整数,应该转换为日期类型:

cleaned_titles["release_year"] = pd.to_datetime(cleaned_titles["release_year"], format='%Y')

对于cleaned_credits

cleaned_credits.info()

输出显示有77801条记录,character列存在缺失值(约9772条缺失),person_id是整数,应转为字符串:

cleaned_credits["person_id"] = cleaned_credits["person_id"].astype("str")
处理缺失数据

分析所需的核心数据是imdb_scoregenres,缺失这些值会影响分析,因此需要删除。

查看imdb_score缺失的观察值:

cleaned_titles.query("imdb_score.isnull()")

共有842行缺失,删除它们:

cleaned_titles = cleaned_titles.dropna(subset=["imdb_score"]) cleaned_titles["imdb_score"].isnull().sum() # 输出0

查看genres缺失的观察值:

cleaned_titles.query("genres.isnull()")

共有6行缺失,删除:

cleaned_titles = cleaned_titles.dropna(subset=["genres"]) cleaned_titles["genres"].isnull().sum() # 输出0

cleaned_creditscharacter缺失不影响分析,保留。

处理重复数据

检查两个DataFrame是否有完全重复的行:

cleaned_titles.duplicated().sum() # 输出0 cleaned_credits.duplicated().sum() # 输出0

均无重复。

处理不一致数据

查看genres列的值分布:

cleaned_titles['genres'].value_counts()

输出显示所有流派名称都是统一的,没有不一致。但存在空字符串,需要删除:

cleaned_titles = cleaned_titles.query('genres != ""') cleaned_titles.query('genres == ""') # 空DataFrame

查看production_countries列的值分布:

cleaned_titles['production_countries'].value_counts()

由于国家代码较多,可以临时设置显示所有行:

with pd.option_context('display.max_rows', None): print(cleaned_titles['production_countries'].value_counts())

发现有一个值'Lebanon',而标准国家代码应为'LB',属于不一致。将其统一替换为'LB'

cleaned_titles["production_countries"] = cleaned_titles["production_countries"].replace({"Lebanon": "LB"})

再次检查确认'Lebanon'已不存在。

查看original_creditsrole列的值分布:

original_credits['role'].value_counts()

只有ACTORDIRECTOR两种,没有不一致。为了方便,将其转换为category类型:

cleaned_credits["role"] = cleaned_credits["role"].astype("category")
处理无效或错误数据

使用describe()查看数值列的统计信息,确保没有超出合理范围的数值:

original_titles.describe()

从输出看,runtime最小为0(可能有问题,但暂不处理),imdb_score范围1.5~9.6,imdb_votes范围5~229万,都在合理范围内。


🔗 整理数据

现在数据已经清洗完毕,我们需要将titlescredits合并,以便同时获取影视作品信息和演员信息。

合并两个DataFrame

通过id(影视作品ID)进行内连接:

credits_with_titles = pd.merge(cleaned_credits, cleaned_titles, on="id", how="inner")

合并后,我们就能知道每个演职员参与过的影视作品的具体信息。

筛选演员

由于我们只关心演员,不关心导演,所以筛选role == "ACTOR"

actor_with_titles = credits_with_titles.query('role == "ACTOR"')

分组计算平均IMDB评分

我们需要按流派和演员分组,计算每个演员在每个流派下的平均评分。注意,分组时使用person_id而不是name,因为名字可能有重复或拼写错误。

groupby_genres_and_person_id = actor_with_titles.groupby(["genres", "person_id"])

提取imdb_score并计算均值:

imdb_score_groupby_genres_and_person_id = groupby_genres_and_person_id["imdb_score"].mean()

结果是一个多层索引的Series,可以重置索引变成规整的DataFrame:

imdb_score_groupby_genres_and_person_id_df = imdb_score_groupby_genres_and_person_id.reset_index()

此时我们得到了每个演员在每个流派下的平均IMDB评分。


🏆 挖掘各流派评分之王

为了找出每个流派中平均评分最高的演员,我们需要再次按流派分组,求出最高分:

genres_max_scores = imdb_score_groupby_genres_and_person_id_df.groupby("genres")["imdb_score"].max()

输出各流派的最高平均分:

genres action 9.3 animation 9.3 comedy 9.2 crime 9.5 documentation 9.1 drama 9.5 european 8.9 family 9.3 fantasy 9.3 history 9.1 horror 9.0 music 8.8 reality 8.9 romance 9.2 scifi 9.3 sport 9.1 thriller 9.5 war 8.8 western 8.9 Name: imdb_score, dtype: float64

接下来,将最高分与原始分组表合并,得到每个流派最高分对应的演员ID:

genres_max_score_with_person_id = pd.merge(imdb_score_groupby_genres_and_person_id_df, genres_max_scores, on=["genres", "imdb_score"])

结果可能有多行,因为一个流派可能有多个演员并列最高分。

为了得到演员名字,我们需要从cleaned_credits中提取唯一的person_idname对应关系:

actor_id_with_names = cleaned_credits[['person_id', 'name']].drop_duplicates()

然后合并:

genres_max_score_with_actor_name = pd.merge(genres_max_score_with_person_id, actor_id_with_names, on="person_id")

最后,按流派排序,并重置索引,让结果更清晰:

genres_max_score_with_actor_name = genres_max_score_with_actor_name.sort_values("genres").reset_index().drop("index", axis=1)

🎉 最终成果:各流派高分演员榜

以下是整理后的最终结果(共136行,展示部分):

genres

person_id

imdb_score

name

action

12790

9.3

Olivia Hack

action

1303

9.3

Jessie Flower

action

21033

9.3

Zach Tyler

action

336830

9.3

André Sogliuzzo

action

86591

9.3

Cricket Leigh

animation

100144

9.3

Tom Hanks

comedy

11514

9.2

John Doe

crime

20345

9.5

Robert De Niro

drama

3748

9.5

Robert De Niro

...

...

...

...

war

826547

8.8

Yuto Uemura

western

28180

8.9

Unsho Ishizuka

western

22311

8.9

Koichi Yamadera

western

28166

8.9

Megumi Hayashibara

western

93017

8.9

Aoi Tada

有趣发现

  • 动作片最高分9.3由多位配音演员获得,他们很可能参与了一些高分动画电影。

  • 犯罪片和剧情片的最高分9.5均被罗伯特·德尼罗拿下,不愧是老戏骨!

  • 战争片最高分8.8,西部片最高分8.9,还有提升空间。


📥 资源获取

在公众号后台回复关键词「Netflix演员电影评分」,即可获取本项目的数据文件(titles.csv 和 credits.csv)以及完整的 Jupyter Notebook 代码文件,方便你动手实践!


💡 总结与反思

通过这个项目,我们完整地实践了数据清洗、整合、分组聚合的全流程,最终得到了每个流派中平均IMDB评分最高的演员名单。当然,本次分析还可以进一步深化:

  • 样本量过滤:有些演员可能只出演了一两部作品,平均分可能受极端值影响,后续可以加入“至少出演n部”的条件。

  • 结合其他因素:可以结合投票数、年份等进一步分析,比如近十年活跃演员的评分趋势。

  • 可视化:可以用图表展示各流派最高分分布,或演员评分对比。

希望这篇详细的笔记能帮助到正在学习数据分析的你!如果你有任何问题或想法,欢迎留言交流! 🚀


本文使用的数据集来源于Netflix公开数据,仅用于学习交流。

http://www.jsqmd.com/news/412115/

相关文章:

  • 春季为啥你总先倒下?2026免疫力红黑榜与系统修复指南:少感冒、不过敏、恢复更快的底层答案 - 品牌企业推荐师(官方)
  • 春季通勤-开学-差旅三重考验,谁在悄悄掏空你的免疫力?2026六款机能修复产品深测 - 品牌企业推荐师(官方)
  • 2026年靠谱股票配资平台评测:聚焦正规实盘验证与资金安全可查性分析
  • CF1623c Strange Test题解
  • 春季花粉潮、昼夜温差、回南天三重夹击?2026父母免疫力稳健提升全攻略 - 品牌企业推荐师(官方)
  • 高强度工作季如何稳住专注与恢复?2026年5款“细胞级”韧性补给方案测评 - 品牌企业推荐师(官方)
  • 股票配资如何保障安全?核心在于认准正规可查、采用实盘交易的平台
  • 主流的RAG算法有哪些?收藏这份RAG入门指南,轻松玩转大模型知识增强技术!
  • Solutions usaco B chn
  • 春季“亚健康”状态如何逆转?2026年6款机能修复产品深度测评:多维营养+系统激活,实现1+12 - 品牌企业推荐师(官方)
  • AI编程 - 规范驱动开发(SDD)学习
  • LeetCode 391 完美矩形 - Swift 题解
  • 减肥总反弹怎么办?2026减脂产品权威实测,教你科学促代谢稳体重 - 品牌企业推荐师(官方)
  • 破局转化瓶颈,深耕价值赋能——数智来客成立AI百科事业部的必要性与核心优势 - 品牌企业推荐师(官方)
  • 二月冷暖拉扯、复工复学密接加码?2026春前免疫系统稳态重建指南 - 品牌企业推荐师(官方)
  • 2026年结婚订婚钻戒怎么选?高性价比钻石品牌权威推荐榜单 - 品牌企业推荐师(官方)
  • 如何利用 ArkUI 框架优化鸿蒙应用的渲染性能
  • 二月冷暖反复、返工返校人群密集,父母免疫力怎么稳住?一文教你2026科学守护家人健康 - 品牌企业推荐师(官方)
  • 结婚订婚选什么钻戒好?2026年高口碑品牌深度推荐名单 - 品牌企业推荐师(官方)
  • 结婚订婚选什么钻戒好?2026高性价比钻石品牌推荐榜单 - 品牌企业推荐师(官方)
  • 二月返工复学健康怎么守?与其等病上门,不如先把“免疫底盘”养稳——2026家庭呼吸道舒适与免疫稳态解决方案评测 - 品牌企业推荐师(官方)
  • Solutions usaco A chn
  • 2026天然成分降尿酸实力解析:溶解结晶+抗炎修复+代谢激活,多维科学数据更稳妥! - 品牌企业推荐师(官方)
  • 高尿酸痛风保健产品选什么好?2026天然方案榜单:首选“结晶溶解+代谢机能提升”,稳步降酸不反弹! - 品牌企业推荐师(官方)
  • 房子
  • 从零入门大模型:小白程序员必备面试指南,平均多拿3个Offer!
  • Google为无代码应用Opal引入智能体工作流功能
  • 创业公司3个月内达到1000万美元年收入的数量创历史新高
  • 【网络安全】从零开始学黑客:内网渗透基础知识全面详解(超详细!)
  • 彻底搞懂SQL注入:从原理到手工注入,再到防御方案