TMDb数据分析报告
碼字不易,謝謝支持。報(bào)告原文、數(shù)據(jù)集和代碼請(qǐng)移步至:https://github.com/Alexander-zhoukai/TMDb-data-analysis-report
學(xué)習(xí)用python進(jìn)行數(shù)據(jù)分析一段時(shí)間了,也跟著書本、網(wǎng)上案例,包括工作中的數(shù)據(jù)做了很多分析工作。用一個(gè)項(xiàng)目做階段性的小結(jié)。
該項(xiàng)目是kaggle上的經(jīng)典項(xiàng)目,美國(guó)百年間的電影數(shù)據(jù)分析,也是一個(gè)基礎(chǔ)數(shù)據(jù)分析項(xiàng)目。
項(xiàng)目數(shù)據(jù)集是tmdb_5000_credits、tmdb_5000_movies,這兩個(gè)文件比較大,這里沒有上傳,鏈接為:https://github.com/Alexander-zhoukai/Analysis-and-Prediction-on-TMDb5000
下面是目錄
第一章 提出問(wèn)題
1.1 項(xiàng)目背景
1.2 提出問(wèn)題
1.3 分析思維
1.4 分析方法和工具
1.5 本項(xiàng)目計(jì)劃
第二章 理解數(shù)據(jù)
2.1 導(dǎo)入包
2.2 導(dǎo)入數(shù)據(jù)
2.3 理解數(shù)據(jù)
第三章 數(shù)據(jù)清洗
3.1 數(shù)據(jù)預(yù)處理
3.2 特征提取
3.3 特征選取
3.4 小結(jié)數(shù)據(jù)清洗報(bào)告
第四章 數(shù)據(jù)分析及可視化
4.1 電影風(fēng)格隨時(shí)間變化的趨勢(shì)
4.2 不同風(fēng)格電影的收益能力
4.3 不同風(fēng)格電影的受歡迎程度
4.4 不同風(fēng)格電影的平均評(píng)分
4.5 不同類型電影的平均評(píng)分次數(shù)
4.6 比較Universal Picture與Paramount Picture兩家巨頭公司的業(yè)績(jī)
4.7 原創(chuàng)電影和改變電影的對(duì)比
4.8 電影票房收入與哪些因素最相關(guān)
4.9 分析結(jié)論
第五章 項(xiàng)目回顧與總結(jié)
下面是報(bào)告正文
第一章 提出問(wèn)題
1.1 項(xiàng)目背景
本報(bào)告數(shù)據(jù)來(lái)源于Kaggle平臺(tái)上的項(xiàng)目TMDb(The Movie Database),主要是1916-2017年百年間美國(guó)電影作品,共有4803部。
通過(guò)對(duì)電影數(shù)據(jù)的分析,利用可視化的方法,發(fā)現(xiàn)電影流行的趨勢(shì),找到電影投資的方向,為行業(yè)新入局者提供參考建議。
本文的重點(diǎn)在于從不同的角度,用數(shù)據(jù)可視化的方法來(lái)分析。未能面面俱到。
1.2 提出問(wèn)題
本次數(shù)據(jù)分析的核心任務(wù)是:通過(guò)歷史電影數(shù)據(jù)的分析,為行業(yè)新入局者提供參考建議。細(xì)分為以下幾個(gè)小問(wèn)題:
問(wèn)題1:電影風(fēng)格隨時(shí)間變化的趨勢(shì);
問(wèn)題2:不同風(fēng)格電影的收益能力;
問(wèn)題3:不同風(fēng)格電影的受歡迎程度;
問(wèn)題4:不同風(fēng)格電影的平均評(píng)分;
問(wèn)題5:不同風(fēng)格電影的平均評(píng)價(jià)次數(shù);
問(wèn)題6:比較Universal Picture與Paramount Picture兩家巨頭公司的業(yè)績(jī);
問(wèn)題7:原創(chuàng)電影和改變電影的對(duì)比;
問(wèn)題8:電影票房收入與哪些因素最相關(guān)。
1.3 分析思維
數(shù)據(jù)分析常用思維有細(xì)分、對(duì)比和溯源。
細(xì)分方法有橫切、縱切和內(nèi)切。
其中橫切是指從各個(gè)維度的各個(gè)點(diǎn)來(lái)分析(如產(chǎn)品、渠道、用戶、營(yíng)銷等維度里面的各個(gè)指標(biāo)點(diǎn));縱切是指通過(guò)漏斗分析、動(dòng)作軌跡分析或者日志來(lái)做分析;內(nèi)切一般是用RFM來(lái)深入分析。對(duì)比指橫切的對(duì)比、縱切的對(duì)比、目標(biāo)的對(duì)比或者時(shí)間上對(duì)比。溯源是指通過(guò)反復(fù)的細(xì)分,反復(fù)的對(duì)比,來(lái)確定關(guān)鍵點(diǎn)所在。
本項(xiàng)目采用的思維是細(xì)分-橫切,從各個(gè)維度分析以找到關(guān)鍵信息。
1.4 分析方法和工具
本項(xiàng)目采用數(shù)據(jù)可視化的方法,來(lái)呈現(xiàn)各部分的分析結(jié)果,回答問(wèn)題用數(shù)說(shuō)話、用圖說(shuō)話。
數(shù)據(jù)分析過(guò)程中使用Python編程語(yǔ)言,數(shù)據(jù)處理使用pandas庫(kù)、numpy庫(kù),可視化需要matplotlib庫(kù)、seaborn 庫(kù)。使用以上方法、工具能較好地完成本項(xiàng)目,是適合的方法和工具。
1.5 本項(xiàng)目計(jì)劃
1月2號(hào),完成第一、二章,前期工作:工具安裝調(diào)試、項(xiàng)目背景和理解數(shù)據(jù)。
1月3、4號(hào),完成第三、四章,主要是編寫代碼:完成數(shù)據(jù)清洗、數(shù)據(jù)分析和可視化。
1月5號(hào),完成第五、六章,文字部分:整理項(xiàng)目資料,編寫輸出文檔、存檔資料。
第二章 理解數(shù)據(jù)
在Kaggle平臺(tái)上找到TMDb項(xiàng)目,下載2個(gè)原始數(shù)據(jù)集:tmdb_5000_movies.txt和tmdb_5000_credits.txt,前者存放電影的基本信息,有20個(gè)字段,后者存放演職人員的信息,有4個(gè)字段。
2.1 導(dǎo)入包
數(shù)據(jù)分析及可視化常用庫(kù):
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import json
import warnings
warnings.filterwarnings(‘ignore’)
plt.rcParams[‘font.sans-serif’] = [‘SimHei’] # 處理中文亂碼
2.2 導(dǎo)入數(shù)據(jù)
movies = pd.read_csv(‘D:/DataAnalysis/cases/TMDb1/tmdb_5000_movies.txt’)
credits= pd.read_csv(‘D:/DataAnalysis/cases/TMDb1/tmdb_5000_credits.txt’)
2.3 理解數(shù)據(jù)
邊看邊觀察,為后續(xù)的處理做準(zhǔn)備。
(1)查看數(shù)據(jù)維度:shape屬性
movies.shape
credits.shape
(2)查看數(shù)據(jù)字段:columns屬性
movies.columns
credits.columns
(3)查看數(shù)據(jù)統(tǒng)計(jì)信息:describe方法
movies.describe()
credits.describe()
(4)查看數(shù)據(jù)框信息:info方法
movies.info()
credits.info()
full.info()
(5)展示數(shù)據(jù)頭:head方法
movies.head()
credits.head()
小結(jié):movies表與credits有2個(gè)重復(fù)字段,id和title,接下來(lái)需要處理;movies表中homepage、release_date、runtime和tagline四個(gè)字段的數(shù)據(jù)均有缺失,也需要處理。
第三章 數(shù)據(jù)清洗
原始數(shù)據(jù)不適宜直接用來(lái)做分析,需要進(jìn)行一系列的清洗,為后面的分析、可視化做好準(zhǔn)備。
數(shù)據(jù)清洗主要分為3部分:預(yù)處理對(duì)數(shù)據(jù)進(jìn)行刪除、填充和合并;特征提取讓數(shù)據(jù)更規(guī)整;特征選取已經(jīng)開始做數(shù)據(jù)分析的前一步,將這一部分合并到下一章。
3.1 數(shù)據(jù)預(yù)處理
3.1.1 刪除行列
credits中的字段title, 與movies中的字段title重復(fù)了,刪除前者。
方法一:del命令
#刪除title列
del credits[‘title’]
#刪除homepage,original_title,overview,spoken_languages,status,tagline,movie_id
del full(‘homepage’)
del full(‘original_title’)
del full(‘overview’)
del full(‘spoken_languages’)
del full(‘status’)
del full(‘tagline’)
del full(‘movie_id’)
方法二:drop方法
#刪除title列
credits.drop(‘title’, axis = 1, inplace = True),或者:
credits = credits.drop(‘title’, axis = 1)
#刪除homepage,original_title,overview,spoken_languages,status等7列
full.drop([‘homepage’, ‘original_title’, ‘overview’, ‘spoken_languages’, ‘status’, ‘tagline’, ‘movie_id’], axis = 1, inplace = True)
3.1.2 填充缺失值
movies中release_date字段的數(shù)據(jù)缺失1條,runtime字段的數(shù)據(jù)缺失2條,需要補(bǔ)充。
方法一:觀察 + 查找 + 填充
#填充release_date字段的缺失值
#先找出release_date字段缺失值所在的行、列位置
#使用了isnull()和布爾索引
movies[‘release_date’].isnull()
movies[movies[‘release_date’].isnull()]
movies.loc[movies[‘release_date’].isnull()]
movies.loc[4553, ‘release_date’] = ‘2010-06-01’
#填充runtime字段的缺失值
#先找出runtime字段缺失值所在的行、列位置
full.loc[full[‘runtime’].isnull()]
full.loc[2656, ‘runtime’] = 94
full.loc[4140, ‘runtime’] = 240
方法二:觀察 + 快速填充
#填充release_date字段的缺失值
movies[‘release_date’][movies[‘release_date’].isnull()] = ‘2010-06-01’
movies[‘release_date’].fillna( ‘2010-06-01’)
#填充runtime字段的缺失值
full[‘runtime’].fillna(94, limit = 1, inplace = True)
full[‘runtime’].fillna(240, limit = 1, inplace = True)
3.1.3 合并表格
方法一:append方法(縱向合并)
方法二:concat方法(頂級(jí)方法用pd調(diào)用)
(用axis參數(shù)來(lái)控制合并的橫縱方向, axis=1橫向合并占內(nèi)存最少)
full = pd.concat([movies, credits], axis = 1),或者:
full = pd.concat([movies, credits], axis = 0),或者:
full = pd.concat([movies, credits])
方法三:merge方法(基類調(diào)用,或者實(shí)例調(diào)用)
full = pd.merge(movies, credits, how = ‘left’, left_on=‘id’, right_on=‘movie_id’)
full1 = movies.merge(credits, how = ‘left’, left_on=‘id’, right_on=‘movie_id’)
方法四:join方法(只能實(shí)例調(diào)用)(數(shù)據(jù)有丟失,本項(xiàng)目該法不可取)
full = movies.join(credits, how = ‘left’, on = ‘id’)
3.2 特征提取
3.2.1 解碼json字符串
方法一:步驟①②,構(gòu)造增廣矩陣,手撕代碼可實(shí)現(xiàn)。
方法二:另外,也可采用生成偽變量生成偽矩陣get_dummies(data, prefix = ‘string’),也叫one-hot-encoding
數(shù)據(jù)中g(shù)enres, keywords, production_companies, production_countries, cast, crew字段均為json類型字符串,要解析出其中的關(guān)鍵信息,需分為兩步apply/map:(1)將json類型字符串,轉(zhuǎn)換為字典;(2)取出字典里面的關(guān)鍵信息。
#新建一個(gè)列表,存放json類型的字段
Cols = [‘genres’, ‘keywords’, ‘production_companies’, ‘production_countries’, ‘cast’, ‘crew’]
#解碼1,將json轉(zhuǎn)換為字典
for col in Cols:
full[col] = full[col].apply(json.loads)
#解碼2,將字典內(nèi)鍵name對(duì)應(yīng)的值取出來(lái)(方法1手撕代碼,方法2列表解析表達(dá)式)
#方法1
def getname(x):
list = []
for i in x:
list.append(i[‘name’])
return ‘,’.join(list)
for col in Cols[0:4]:
full[col] = full[col].apply(getname)
#方法2列表解析表達(dá)式
def getname(x):
list = [i[‘name’] for i in x]
return ‘,’.join(list)
for col in Cols[0:4]:
full[col] = full[col].apply(getname)
#繼續(xù)解碼2,將字典內(nèi)鍵charactor主演對(duì)應(yīng)的值取出來(lái)
def getcharacter(x):
list = [i[‘character’] for i in x]
return ‘,’.join(list[0:2])
full[‘cast’] = full[‘cast’].apply(getcharacter)
#繼續(xù)解碼2,將字典內(nèi)鍵Director導(dǎo)演對(duì)應(yīng)的值取出來(lái)
def getdirector(x):
list = [i[‘name’] for i in x if i[‘job’] == ‘Director’]
return ‘,’.join(list)
full[‘crew’] = full[‘crew’].apply(getdirector)
3.2.2 去重
去重操作應(yīng)用了:
數(shù)據(jù)結(jié)構(gòu):字符串、集合、列表、
字符串:str, split()
集合:union(), remove(),update(), discard()
提取所有的電影風(fēng)格,該過(guò)程需要去重。從在genres字段中提出來(lái)的數(shù)據(jù)會(huì)重復(fù)。
方法一:常規(guī)4步。注意union是頂級(jí)方法。注意去空值。
genreset = set()
for x in full[‘genres’].str.split(’,’):
genreset = set().union(genreset, x)
genreset.remove(’’)
genrelist = list(genreset)
方法二:少用的4步。update比union簡(jiǎn)單,discard與remove效果一樣。
genreset = set()
for x in full[‘genres’].str.split(’,’):
genreset.update(x)
genreset.discard(’’)
genrelist = list(genreset)
3.2.3 數(shù)字化
方法1:五合一,df[‘name’].str.contains(‘a(chǎn)bc’).map(lambda x:1 if x else 0)。
方法2:快捷pd.get_dummies(data, prefix = ‘a(chǎn)aa’)
該過(guò)程也叫one-hot-encoding,涉及到的名詞有增廣矩陣、偽矩陣、啞矩陣、啞變量、偽變量、數(shù)字化、二值化、map(字典)。兩個(gè)方法的差異在于’name’字段的各個(gè)數(shù)據(jù)有1個(gè)還是多個(gè)偽變量。
本項(xiàng)目數(shù)據(jù)的genres列有多個(gè)偽變量,適合用方法一來(lái)處理。
#新建數(shù)據(jù)框df
genre_df = pd.DataFrame()
#五合一,進(jìn)行one-hot-encoding,為genre_df的20個(gè)列賦值
for genre in genrelist:
genre_df[genre] = full[‘genres’].str.contains(genre).map(lambda x: 1 if x else 0)
3.2.4 類型轉(zhuǎn)換
重點(diǎn)提一下時(shí)間類型的轉(zhuǎn)換,帶格式化的。
數(shù)據(jù)中release_date字段是字符串類型的,先轉(zhuǎn)換為日期類型,再取年份,得整型。
full[‘release_date’] = pd.to_datetime(full[‘release_date’], format = ‘%Y-%m-%d’).dt.year
3.2.5 重命名列
對(duì)處理過(guò)的字段release_date, cast和crew,進(jìn)行重命名。
name_dict = {‘release_date’: ‘year’, ‘cast’: ‘a(chǎn)ctor’, ‘crew’: ‘director’}
full.rename(columns = name_dict, inplace = True)
3.3 特征選取
在分析每個(gè)小問(wèn)題之前,有一個(gè)重要的步驟,是通過(guò)選取特征構(gòu)造出合適的數(shù)據(jù)框,以便高效地進(jìn)行分析并輸出可視化圖形。
在解決前面提出的若干問(wèn)題過(guò)程中,會(huì)頻繁地構(gòu)造數(shù)據(jù)框,這里有一個(gè)小竅門就是:在分析每一個(gè)小問(wèn)題時(shí),選取要分析的數(shù)據(jù)列,忽略與本問(wèn)題無(wú)關(guān)的數(shù)據(jù)列,或者再添加特定序列,從而構(gòu)造出一個(gè)新數(shù)據(jù)框,而不是在原始數(shù)據(jù)上做分析動(dòng)作,否則后面思維越來(lái)越混亂,數(shù)據(jù)混淆在一起了。
需要注意的是,數(shù)據(jù)復(fù)雜度有三個(gè)層次,依次是DataFrame、Series、List/Dict/Index,在構(gòu)造數(shù)據(jù)框的時(shí)候參考這三個(gè)層次,盡量避免構(gòu)造復(fù)雜度高的數(shù)據(jù)。
3.3.1 構(gòu)造Series
方法1:在原始數(shù)據(jù)框中截取;
方法2:使用Series定義,List/Dict–>Series。
3.3.2 構(gòu)造DataFrame
方法1:在原始數(shù)據(jù)框中截取;
方法2:使用DataFrame定義,Series/List/Dict/Index–>DataFrame;
方法3:合并;
方法3:計(jì)算。
3.4 小結(jié)數(shù)據(jù)清洗報(bào)告
在數(shù)據(jù)清洗這一部分,刪除了title、homepage,original_title等8列,填充了runtime, release_date列的缺失值,合并了movies和credits兩個(gè)表格,對(duì)6個(gè)json類數(shù)據(jù)進(jìn)行解碼提出關(guān)鍵信息,對(duì)genres列做了one-hot編碼,對(duì)release_date做了類型轉(zhuǎn)換,并對(duì)3個(gè)列進(jìn)行了重命名,最終得到的數(shù)據(jù)框full,4308行,16列,數(shù)據(jù)框genre_df,4308行,20列。
第四章 數(shù)據(jù)分析及可視化
對(duì)1.2中的九個(gè)問(wèn)題逐個(gè)分析。
數(shù)據(jù)可視化是對(duì)每一個(gè)問(wèn)題,每一個(gè)特定的數(shù)據(jù)框進(jìn)行可視化,發(fā)現(xiàn)數(shù)據(jù)背后的規(guī)律和真相。
常用圖形有散點(diǎn)圖、柱狀圖、直方圖、折線圖、餅圖、箱線圖和詞云圖;較為常用的圖形有:小提琴圖。
4.1 電影風(fēng)格隨時(shí)間變化的趨勢(shì)
4.1.1 構(gòu)造數(shù)據(jù)框
#1、構(gòu)造數(shù)據(jù)框(截取+合并)
genre_df[‘year’] = full[‘year’]
#各種類型電影的數(shù)量隨時(shí)間變化的趨勢(shì)genre_by_year
genre_by_year = genre_df.groupby(‘year’).sum()
#各種類型電影的總數(shù)genreSum_by_year
#升序
genreSum_by_year = genre_by_year.sum().sort_values()
#降序
genreSum_by_year = genre_by_year.sum().sort_values(ascending = False)
4.1.2 可視化
#可視化genreSum_by_year
from pylab import rcParams
params = {‘legend.fontsize’: 12,
‘legend.handlelength’: 10}
rcParams.update(params)
fig = plt.figure(figsize=(20, 5))
ax = plt.subplot(1, 1, 1)
ax = genreSum_by_year.plot(kind = ‘bar’)
plt.title(‘Film genre by year’, fontsize = 18)
plt.xlabel(‘genre’, fontsize = 18)
plt.ylabel(‘a(chǎn)mount’, fontsize = 18)
fig.savefig(‘Film genre by year.png’)
#可視化genre_by_year
from pylab import rcParams
params = {‘legend.fontsize’: 10,
‘legend.handlelength’: 3}
rcParams.update(params)
#genre_by_year = genre_by_year.loc[1960:2020, :]
fig = plt.figure(figsize=(20, 12))
plt.xlabel(‘Year’, fontsize = 10)
plt.ylabel(‘Amount’, fontsize = 10)
plt.xticks(range(1920, 2030, 5))
plt.title(‘Film amount by year’, fontsize = 10)
plt.plot(genre_by_year)
plt.legend(genre_by_year, loc = ‘best’)
#plt.legend(genre_by_year, loc = ‘best’, ncol = 2)
fig.savefig(‘Film amount by year_8.png’)
#genre_by_year.plot() #理解為默認(rèn)設(shè)置,不同于上面設(shè)定了各個(gè)參數(shù)
4.1.3 分析結(jié)果
(1)從上世紀(jì)90年代開始,整個(gè)電影市場(chǎng)各種類型的電影數(shù)量呈現(xiàn)爆發(fā)式增長(zhǎng);
(2)其中Drama、Comedy、Thriller、Romance、Adventure這五類類電影增長(zhǎng)最快。
4.2 不同風(fēng)格電影的收益能力
4.2.1 構(gòu)造數(shù)據(jù)框
#構(gòu)造數(shù)據(jù)框(定義+合并+截取+計(jì)算)
full[‘profit’] = full[‘revenue’] - full[‘budget’]
profit_df = pd.DataFrame()
profit_df = pd.concat([genre_df.iloc[:, :-1], full[‘profit’]], axis = 1)
#各種類型電影的收益profit_by_genre
#構(gòu)造Series,保存profit,其index為電影類型genrelist。(定義+計(jì)算)
#此處的計(jì)算是重點(diǎn),要理解數(shù)據(jù)框結(jié)構(gòu),掌握計(jì)算邏輯,靈活運(yùn)用。
profit_by_genre = pd.Series(index = genrelist)
for gen in genrelist:
profit_by_genre.loc[gen] = profit_df.loc[:, [gen, ‘profit’]].groupby(gen).sum().loc[1, ‘profit’]
#排序,升序
profit_by_genre = profit_by_genre.sort_values()
4.2.2 可視化
fig = plt.figure(figsize=(20, 12))
plt.xlabel(‘Profit’, fontsize = 12)
plt.ylabel(‘Genre’, fontsize = 12)
plt.title(‘Profit by Genre’, fontsize = 12)
profit_by_genre.plot(kind = ‘barh’)
fig.savefig(‘Profit by Genre_1.png’)
#構(gòu)造分析budget的數(shù)據(jù)框并可視化
budget_df = pd.DataFrame()
budget_df = pd.concat([genre_df.iloc[:, :-1], full[‘budget’]], axis = 1)
budget_by_genre = pd.Series(index = genrelist)
for gen in genrelist:
budget_by_genre.loc[gen] = budget_df.loc[:, [gen, ‘budget’]].groupby(gen).sum().loc[1, ‘budget’]
budget_by_genre = budget_by_genre.sort_values()
fig = plt.figure(figsize=(20, 12))
plt.xlabel(‘Budget’, fontsize = 15)
plt.ylabel(‘Genre’, fontsize = 15)
plt.title(‘Budget by Genre’, fontsize = 15)
profit_by_genre.plot(kind = ‘barh’)
fig.savefig(‘Budget by Genre_1.png’)
4.2.3 分析結(jié)果
可以看出Adventure、Action、Comedy、Drama和Thriller電影收益最高。
4.3 不同風(fēng)格電影的受歡迎程度
4.3.1 構(gòu)造數(shù)據(jù)框popu_by_genre
popu_df = pd.DataFrame()
popu_df = pd.concat([genre_df.iloc[:, :-1], full[‘popularity’]], axis = 1)
popu_by_genre = pd.Series(index = genrelist)
for gen in genrelist:
popu_by_genre.loc[gen] = popu_df.loc[:, [gen, ‘popularity’]].groupby(gen).mean().loc[1, ‘popularity’]
popu_by_genre.sort_values(inplace=True)
4.3.2 可視化
fig = plt.figure(figsize=(20, 12))
plt.xlabel(‘Mean of popularity’, fontsize = 15)
plt.ylabel(‘Genre’, fontsize = 15)
plt.title(‘Mean of popularity’, fontsize = 15)
popu_by_genre.plot(kind = ‘barh’)
fig.savefig(‘popularity_by_genre_1.png’)
4.3.3 分析結(jié)果
可以看出,Adventure、Animation最受歡迎
4.4 不同風(fēng)格電影的平均評(píng)分
4.4.1 構(gòu)造數(shù)據(jù)框vote_avg_by_genre
vote_avg_df = pd.DataFrame()
vote_avg_df = pd.concat([genre_df.iloc[:, :-1], full[‘vote_average’]], axis = 1)
vote_avg_by_genre = pd.Series(index = genrelist)
for gen in genrelist:
vote_avg_by_genre.loc[gen] = vote_avg_df.loc[:, [gen, ‘vote_average’]].groupby(gen).mean().loc[1, ‘vote_average’]
vote_avg_by_genre.sort_values(inplace=True) #排序、升序
full[‘popularity’].corr(full[‘vote_average’]) #相關(guān)性值為: 0.27
#可以看出,電影的平均受歡迎程度與平均評(píng)分的相關(guān)性很低
4.4.2 可視化
fig = plt.figure(figsize=(20, 12))
plt.xlabel(‘vote_average’, fontsize = 15)
plt.ylabel(‘Genre’, fontsize = 15)
plt.xlim(5, 7, 0.5)
#plt.xticks(range(5, 7, 1)) # 給效果不夠好。
plt.title(‘vote avg by genre’, fontsize = 15)
vote_avg_by_genre.plot(kind = ‘barh’)
fig.savefig(‘vote_avg_by_genre_3.png’)
4.4.3 分析結(jié)果
不同類型電影的平均評(píng)分,數(shù)據(jù)很接近。沒有顯著的差異,最低值與最高值的差距不到1
#另外,也可以可視化全部平均分,用頻率分布直方圖sns.distplot(data, bins=)
fig = plt.figure(figsize=(20, 12))
plt.xlabel(‘vote_average’, fontsize = 12)
plt.ylabel(‘distributio of vote_avg’, fontsize = 12)
plt.xticks(range(11))
plt.title(‘vote avg by genre’, fontsize = 12)
sns.distplot(full[‘vote_average’], bins = 30)
fig.savefig(‘distributio of vote_avg.png’)
#分析結(jié)果
#不同類型電影的平均評(píng)分,在5-8之間
4.5 不同類型電影的平均評(píng)分次數(shù)
4.5.1 構(gòu)造數(shù)據(jù)框vote_count_df、vote_count_avg_by_genre
vote_count_df = pd.DataFrame()
vote_count_df = pd.concat([genre_df.iloc[:, :-1], full[‘vote_count’]], axis = 1)
vote_count_avg_by_genre = pd.Series(index = genrelist)
for gen in genrelist:
vote_count_avg_by_genre.loc[gen] = vote_count_df.loc[:, [gen, ‘vote_count’]].groupby(gen).mean().loc[1, ‘vote_count’]
vote_avg_by_genre.sort_values(inplace=True)
4.5.2 可視化
fig = plt.figure(figsize=(20, 12))
plt.xlabel(‘a(chǎn)mount’, fontsize = 15)
plt.ylabel(‘Genre’, fontsize = 15)
plt.title(‘vote_count_avg_by_genre’, fontsize = 15)
vote_count_avg_by_genre.plot(kind = ‘barh’)
fig.savefig(‘vote_count_avg_by_genre_1.png’)
4.5.3 分析結(jié)果
可以看出,Adventure、Science Fiction兩類電影獲得的評(píng)價(jià)平均次數(shù)是最多的。
4.6 比較Universal Picture與Paramount Picture兩家巨頭公司的業(yè)績(jī)
4.6.1 構(gòu)造數(shù)據(jù)框
#構(gòu)造兩公司業(yè)績(jī)數(shù)據(jù)框revenue_by_company
#公司列表company
company_list = [‘Paramount Pictures’, ‘Universal Pictures’]
company_df = pd.DataFrame()
for company in company_list:
company_df[company] = full[‘production_companies’].str.contains(company).apply(lambda x: 1 if x else 0)
#company_df = pd.merge([company_df, genre_df.loc[:, :-1], full[‘revenue’]], axis = 1)
company_df = pd.concat([company_df, full[‘revenue’]], axis = 1)
revenue_by_company = pd.Series(index = company_list)
for company in company_list:
revenue_by_company.loc[company] = company_df.loc[:, [company, ‘revenue’]].groupby(company).sum().loc[1, ‘revenue’]
4.6.2 可視化
fig = plt.figure(figsize=(20, 12))
plt.xlabel(‘a(chǎn)mount’, fontsize = 15)
plt.ylabel(‘Genre’, fontsize = 15)
plt.title('Paramount vs Universal ', fontsize = 15)
revenue_by_company.plot(kind = ‘barh’)
fig.savefig(‘revenue_by_company_1.png’)
4.6.3 分析結(jié)果
Universal Pictures公司的票房收入高于Paramount Pictures公司
4.7 原創(chuàng)電影和改變電影的對(duì)比
該問(wèn)題繼續(xù)細(xì)分為原創(chuàng)電影和改編電影數(shù)量的對(duì)比、利潤(rùn)的對(duì)比
4.7.1 構(gòu)造數(shù)據(jù)框
#原創(chuàng)電影和改編電影數(shù)量的對(duì)比
#原創(chuàng)的電影:original - based on = false
#改編來(lái)的電影:recompose - based on = true
original_recompose_list = [‘original’, ‘recompose’]
original_recompose_df = pd.DataFrame()
original_recompose_df[‘type’] = full[‘keywords’].str.contains(‘based on’).apply(lambda x: 1 if x else 0)
#original_vs_recompose = pd.DataFrame(index = original_recompose_list, columns = [‘count’, ‘budget’, ‘revenue’, ‘profit’])
original_vs_recompose = pd.Series(index = original_recompose_list )
original_vs_recompose[‘original’] = original_recompose_df.groupby(‘type’).type.count().loc[0]
original_vs_recompose[‘recompose’] = original_recompose_df.groupby(‘type’).type.count().loc[1]
4.7.2 可視化
#可視化
fig = plt.figure(figsize=(10, 8))
plt.xlabel(‘company’, fontsize = 10)
plt.ylabel(‘count’, fontsize = 10)
plt.title('Paramount vs Universal ', fontsize = 10)
original_vs_recompose.plot(kind = ‘bar’)
fig.savefig(‘original_vs_recompose_1.png’)
4.7.3 分析結(jié)果
#原創(chuàng)電影的數(shù)量遠(yuǎn)多于改編電影
#補(bǔ)充
#原創(chuàng)電影和改變電影利潤(rùn)的對(duì)比
#構(gòu)造數(shù)據(jù)框
prof_original_recompose = pd.Series(index = original_recompose_list)
prof_original_recompose[‘original’] = original_recompose_df.groupby(‘type’).profit.sum().loc[0]
prof_original_recompose[‘recompose’] = original_recompose_df.groupby(‘type’).profit.sum().loc[1]
#可視化
fig = plt.figure(figsize=(10, 8))
plt.xlabel(‘company’, fontsize = 10)
plt.ylabel(‘count’, fontsize = 10)
plt.title('profit Paramount vs Universal ', fontsize = 10)
prof_original_recompose.plot(kind = ‘bar’)
fig.savefig(‘profit Paramount vs Universal_1.png’)
#分析結(jié)果
#原創(chuàng)電影的利潤(rùn)遠(yuǎn)遠(yuǎn)多于改編電影
4.8 電影票房收入與哪些因素最相關(guān)
4.8.1 構(gòu)造數(shù)據(jù)框
full[[‘budget’, ‘popularity’, ‘revenue’, ‘runtime’, ‘vote_average’, ‘vote_count’]].corr()
full[[‘budget’, ‘popularity’, ‘revenue’, ‘runtime’, ‘vote_average’, ‘vote_count’]].corr().iloc[2]
#票房收入與預(yù)算、受歡迎程度、評(píng)價(jià)次數(shù)三個(gè)指標(biāo)相關(guān)性較強(qiáng)
revenue_df = full[[‘popularity’, ‘vote_count’, ‘budget’, ‘revenue’]]
4.8.2 可視化
#三個(gè):散點(diǎn)圖+線性回歸線
fig = plt.figure(figsize = (15, 5))
ax1 = plt.subplot(1, 3, 1)
ax1 = sns.regplot(x=‘popularity’, y=‘revenue’, data = revenue_df)
ax1.text(400, 3e9, ‘r=0.64’, fontsize=12)
plt.xlabel(‘popularity’, fontsize=12)
plt.ylabel(‘revenue’, fontsize=12)
plt.title(‘revenue by popularity’, fontsize=15)
ax2 = plt.subplot(1, 3, 2)
ax2 = sns.regplot(x=‘vote_count’, y=‘revenue’, data = revenue_df, color=‘g’)
ax2.text(5800, 2.1e9, ‘r=0.78’, fontsize=12)
plt.xlabel(‘vote_count’, fontsize=12)
plt.ylabel(‘revenue’, fontsize=12)
plt.title(‘revenue by vote_count’, fontsize=15)
ax3 = plt.subplot(1, 3, 3)
ax3 = sns.regplot(x=‘budget’, y=‘revenue’, data = revenue_df, color=‘r’)
ax3.text(1.6e8, 2.1e9, ‘r=0.73’, fontsize=12)
plt.xlabel(‘budget’, fontsize=12)
plt.ylabel(‘revenue’, fontsize=12)
plt.title(‘revenue by budget’, fontsize=15)
fig.savefig(‘revenue.png’)
4.8.3 分析結(jié)果
票房收入與預(yù)算、受歡迎程度、評(píng)價(jià)次數(shù)三個(gè)指標(biāo)相關(guān)性較強(qiáng)。
4.9 分析結(jié)論
(1)從上世紀(jì)90年代開始,整個(gè)電影市場(chǎng)各種類型的電影數(shù)量呈現(xiàn)爆發(fā)式增長(zhǎng);
(2)其中Drama、Comedy、Thriller、Romance、Adventure這五類類電影增長(zhǎng)最快;
(3)可以看出Adventure、Action、Comedy、Drama和Thriller電影收益最高;
(4)不同類型電影的平均評(píng)分,數(shù)據(jù)很接近,沒有顯著的差異,最低值與最高值的差距不到1, 不同類型電影的平均評(píng)分,在5-8之間。
(5)Adventure、Science Fiction兩類電影獲得的評(píng)價(jià)平均次數(shù)是最多的;
(6)Universal Pictures公司的票房收入高于Paramount Pictures公司;
(7)原創(chuàng)電影的數(shù)量、利潤(rùn)遠(yuǎn)多于改編電影;
(8)票房收入與預(yù)算、受歡迎程度、評(píng)價(jià)次數(shù)三個(gè)指標(biāo)相關(guān)性較強(qiáng)。
第五章 項(xiàng)目回顧與總結(jié)
本項(xiàng)目是我在學(xué)習(xí)用Python進(jìn)行數(shù)據(jù)分析的過(guò)程中,做的一個(gè)練習(xí)項(xiàng)目,按照最常見的典型步驟——提出問(wèn)題、理解數(shù)據(jù)、數(shù)據(jù)清洗、數(shù)據(jù)分析及可視化、項(xiàng)目報(bào)告——對(duì)TMDb做數(shù)據(jù)分析。
數(shù)據(jù)集來(lái)源于Kaggle平臺(tái)上的經(jīng)典項(xiàng)目TMDb(The Movie Database),數(shù)據(jù)集共兩個(gè)文檔:tmdb_5000_movies和tmdb_5000_credits。由于現(xiàn)在Kaggle官方網(wǎng)站無(wú)法注冊(cè),導(dǎo)致無(wú)法下載數(shù)據(jù)集,所以本項(xiàng)目數(shù)據(jù)集并不是在Kaggle上下載的,而是查閱了網(wǎng)上很多對(duì)TMDb進(jìn)行數(shù)據(jù)分析文章的附件里下載的,兩個(gè)數(shù)據(jù)集都是txt格式的。
對(duì)這些數(shù)據(jù)進(jìn)行分析的目的是發(fā)現(xiàn)電影流行的趨勢(shì),找到電影投資的方向,為行業(yè)新入局者提供參考建議。分析思路采用了細(xì)分-橫切,從各個(gè)維度分析得到關(guān)鍵信息,分析方法采用了可視化。使用的主要軟件工具有Python編程語(yǔ)言、pandas數(shù)據(jù)分析庫(kù)。
在數(shù)據(jù)清洗過(guò)程中,盡量采用了多種方法來(lái)完成,體會(huì)了各自的差異和優(yōu)劣,并加深印象,重難點(diǎn)在特征提取這一節(jié),靈活運(yùn)用各種方法才能讓腳本更高效簡(jiǎn)潔。
數(shù)據(jù)分析及可視化的過(guò)程,重點(diǎn)在與構(gòu)造合適的數(shù)據(jù)框,涉及到pandas中重要的分組和聚合。構(gòu)造數(shù)據(jù)框的操作也是多樣靈活的,需要多多聯(lián)系、思考和總結(jié)。可視化操作按照一套基本固定的程序來(lái)實(shí)現(xiàn)就好。
本次數(shù)據(jù)分析項(xiàng)目所做的工作,還存在著不足的地方,下一步需要繼續(xù)補(bǔ)充并掌握以下幾個(gè)方面的內(nèi)容:
(1)對(duì)各種常用分析思維做綜述(介紹、特點(diǎn)、對(duì)比);
(2)對(duì)各種常用方法和工具做綜述(介紹、特點(diǎn)、對(duì)比);
(3)對(duì)數(shù)據(jù)清洗的常用方法、函數(shù),要進(jìn)一步熟練并掌握;
(4)對(duì)于有次坐標(biāo)軸的圖形如何調(diào)用函數(shù)、設(shè)置參數(shù)。
(5)使用詞云圖
總結(jié)
以上是生活随笔為你收集整理的TMDb数据分析报告的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python贪吃蛇小游戏
- 下一篇: C语言实现队列