數據分析:IMDB電影分析報告

前言

本文適合python初學者,通過一個IMDB電影分析數據,了解數據分析的基本過程:問題分解,數據清洗,數據可視化,因為作者也是菜鳥,分析出來的結果可能沒太多價值,但通過此項目分析,從中學到了很多,非常願意分享出來,與大家一起學習進步。

目錄

  1. 識別問題
  2. 理解數據
  3. 清洗數據
  4. 數據可視化

上面只是對數據分析過程簡化,如果具體細分,可以分成很多步驟

1、識別問題

針對互聯網資料庫(IMDB)中共5000部電影,對電影分類,預算與票房收入,導演,評分等重要元素進行研究,本次主要圍繞以下問題進行展開。

  • 電影評分隨著時間的趨勢是什麼?能說明問題?
  • 電影類型隨著時間怎麼變化?能說明問題?
  • 挑選出兩家電影製作公司,對比情況如何?
  • 我們如何通過導演判斷電影是否值得看?
  • 從哪些熱度詞中,能否判斷觀眾偏好?

2、理解數據

採集數據

  • 方法一: 從互聯網電影資料庫IMDB利用Python爬蟲框架Scrapy進行電影信息爬蟲,將提取的信息保存到.csv文件中,如何爬蟲參考該篇文章,爬蟲數據(作者未學習爬蟲,後續補充)
  • 方法二: kaggleIMBD電影項目下載數據Kaggle IMDB 5000 Moives(選用該方法)

導入數據

代碼部分如下:

#導入包import pandas as pdimport matplotlib.pyplot as pltimport seaborn as snssns.set_style(darkgrid)%matplotlib inlineimport jsonimport numpy as npimport warningswarnings.filterwarnings(ignore)#詞雲包from wordcloud import WordCloud,ImageColorGenerator,STOPWORDSfrom PIL import Image# 讀取csv文件# 電影數據movies = pd.read_csv(./tmdb_5000_movies.csv)# 演職人員名單credits = pd.read_csv(./tmdb_5000_credits.csv)

遇到的坑

安裝wordcloud一直安裝不成功,使用pip install wordcloud無法裝上,最後通過lfd.uci.edu/~gohlke/pyt地址下載好相應的文件,pip install <filename>將詞雲才裝上,更多方法參考該文章pip 安裝 wordcloud

探索數據

首先,對數據中變數的含義進行梳理:

梳理如下:電影數據中有20個變數,演員名單中有4個變數,變數如下:

1、budget 預算

2、genres 電影風格

3、homepage 電影首頁的URL

4、id:標識號

5、keywords 關鍵字

6、original_language: 電影語言

7、original_title: 電影名稱

8、overview:劇情概要

9、popularity:在Movie Database 上的相對頁面查看次數,受歡迎度

10、production_companies:製作公司

11、prodacution_countries: 製作國家

12、release_date: 上映時間

13、revenue: 收入

14、runtime: 電影時長

15、spoken_languages 口語

16、status:狀態

17、tagline: 電影的標語

18、title: 主題

19、vote_average: 平均評分

20、vote_count:評分次數

21、title:電影名稱

22、 movie_id 電影編號

23、cast 演員信息

24、crew 劇組演員信息

初步信息觀察,發現兩個重複數據:電影編號,電影名稱,因共有22個變數,

根據項目目標,初步猜測,哪些變數會對我們提出的問題有比較重要的影響

  • 電影評分隨著時間的趨勢是什麼?能說明問題?

vote_average & release_date

  • 電影類型隨著時間怎麼變化?能說明問題?

genres & release_date

  • 挑選出兩家電影製作公司,對比情況如何?

production_companies & budget &revenue

  • 我們如何通過導演判斷電影是否值得看?

vote_average & crew

  • 從哪些熱度詞中,能否判斷觀眾偏好?

keywords

代碼部分如下:

#合併數據movie_credit = pd.concat([movies,credits],axis = 1)#刪除數據delete_column = [homepage, id, original_language, overview, production_countries, spoken_languages, status, title,tagline,movie_id]movie_credit.drop(delete_column,axis=1, inplace = True)movie_credit.infor()

初步發現數據集中共有4803行數據

  1. genres、keywords、production_companies、cast、crew需要處理數據格式,將json格式轉化為字元串
  2. 數據類型缺失 release_date 缺失數據一條, runtime 缺失數據兩條

代碼部分如下:

#json 轉化為字元串json_columns = [genres, keywords, production_companies, crew , cast]for columns in json_columns: movie_credit[columns] = movie_credit[columns].apply(json.loads)def get_names(keywords): return ,.join(x[name] for x in keywords)#castmovie_credit[cast] = movie_credit[cast].apply(get_names)#genresmovie_credit[genres] = movie_credit[genres].apply(get_names)#keywordsmovie_credit[keywords] = movie_credit[keywords].apply(get_names)#production_companisemovie_credit[production_companies] = movie_credit[production_companies].apply(get_names)#crew---directordef director(x): for i in x: if i[job] == Director: return i[name]movie_credit[crew] = movie_credit[crew].apply(director)

遇到的難題

不清楚如何處理數據框中對象元素,如何轉換成字元串,如何遍歷對象中元素,最後參看案例代碼和網上查找相關方法,非常艱難才學會。

3、數據清洗

列名重命名

代碼部分如下:

colNameDict = {original_title:movie_title, release_date : release_year, crew : director}#數據類型轉化,日期類型轉化movie_credit.rename(columns = colNameDict,inplace = True)

缺失值處理

電影上映時間,缺失一組數據; 影片長度,缺失兩組數據,可以在網上找到相應電影進行處理

代碼部分如下:

#缺失率計算missing_df = movie_credit.isnull().sum(axis = 0).reset_index()missing_df.columns= [columns_name,missing_count]missing_df[filling_factor] = (movie_credit.shape[0] - missing_df[missing_count])/movie_credit.shape[0] * 100missing_df.sort_values(filling_factor).reset_index(drop = True)#releasedate_temp = movie_credit[release_year].isnull()#網上找到具體時間,2017-11-01 補充進行去movie_credit[release_year]=movie_credit[release_year].fillna(2014-06-01)movie_credit[release_year]=pd.to_datetime(movie_credit[release_year],format=%Y-%m-%d)#runtimeruntime_temp = movie_credit[runtime].isnull()#網上找到具體時間,2017-11-01 補充進行去movie_credit.loc[2656, runtime] = 98.0movie_credit.loc[4140, runtime] = 81.0

數據類型轉化

處理時間類型數據

代碼部分如下:

#字元串轉化為時間類型,提取年movie_credit[release_year] = movie_credit[release_year].dt.year.apply(int)

4、數據可視化

  • 電影評分隨著時間的趨勢是什麼?能說明問題?

近些年的評分越來越低,從評分均值上看,一直處於下滑狀態,推測近年來,電影雖數量大幅上升,而電影質量整體下滑,因而評分普遍低。

代碼部分如下:

#篩選4分以上的評分scores =movie_credit[movie_credit[vote_average] >4].sort_values(by = vote_average, ascending = False)scores_year = scores.groupby(release_year)[vote_average].mean()scores_year = scores_year[40:89]#繪製評分&年份均值折線圖fg = plt.figure(figsize=(10,6))ax1 = fg.add_subplot(1,1,1)scores_year.plot(x =scores_year.index, y = vote_average, label = 評分趨勢, ax = ax1)plt.title(均值評分&年份, fontsize = 16)plt.xticks(fontsize = 14)plt.yticks(fontsize = 14)plt.xlabel(年份, fontsize =16)plt.ylabel(均值, fontsize =16)plt.legend(fontsize = 13)plt.show()

  • 電影類型隨著時間怎麼變化?能說明問題?

可以看出,1986年到2016年,電影產量隨著時間在不斷的增長,從1999年起電影的數量增幅不大。

電影類型隨時間變化曲線

電影類型佔比

在1990年-2006年間增幅最大,戲劇(Drama)增長最快,喜劇(Comedy)次之,從類型佔比餅圖也可一發現當今電影主流以戲劇、喜劇為主。

代碼部分如下:

#一部電影有多個種類,需要分出來,轉化為列表,匯總movie_credit[genres] = movie_credit[genres].str.split(,)#類型匯總為列表list1=[]for i in movie_credit[genres]: list1.extend(i)#統計同類型的頻率genres=pd.Series(list1).value_counts().sort_values(ascending=True)genres=genres.drop()#類型匯總為set(去掉重複)min_year = movie_credit[release_year].min()max_year = movie_credit[release_year].max()liste_genres = set()for s in movie_credit[genres]: liste_genres = set().union(s, liste_genres)liste_genres = list(liste_genres )liste_genres[1:]#建立時間與電影的類型映射關係genre_df = pd.DataFrame( index = liste_genres[1:],columns= range(min_year, max_year + 1))genre_df = genre_df.fillna(value = 0)year = np.array(movie_credit[release_year])z = 0for i in movie_credit[genres]: split_genre = list(i) for j in split_genre: if j != : genre_df.loc[j, year[z]] = genre_df.loc[j, year[z]] + 1 z+=1genre_df.head(10)genre_df = genre_df.Tnew = genre_df.sum()new[70:100]#繪製電影數量與時間變化圖表plt.rcParams[font.sans-serif]=[SimHei]#中文顯示plt.rcParams[axes.unicode_minus]=Falseplt.subplots(figsize=(18,8))ax = new[70:100].plot.bar(width_=0.7)plt.xticks(fontsize=13)plt.yticks(range(0,1000,100), fontsize=13)plt.title(年份&電影數量, fontsize = 16)plt.show()# 繪製佔比圖f, ax = plt.subplots(figsize = (10, 6))explod_pec = genres_columns.values/genres_columns.sum()explode = (explod_pec > 0.2)/10labels = []for i in genres_columns.index: labels.append(i)fracs = []for j in genres_columns.values: fracs.append(j)plt.pie(x = fracs, labels = labels,explode=explode, autopct=%1.1f%%,pctdistance=0.8, shadow=True,startangle = 90) plt.show() #繪製電影類型與時間變化圖表fg = plt.figure(figsize=(10,8))ax1 = fg.add_subplot(1,1,1)line_style = {Drama : d-, Comedy : m-, Thriller : k-, Action : y-, Romance : p-}for key, value in line_style.items(): genre_df.plot(x =genre_df.index, y = key, label = key, ax = ax1)plt.title(Genres VS Year, fontsize = 16)plt.xticks(fontsize = 14)plt.yticks(fontsize = 14)plt.xlabel(Year, fontsize =16)plt.ylabel(Genres, fontsize =16)plt.legend(fontsize = 13)plt.show()

  • 挑選出兩家電影製作公司,對比情況如何?

對比Universal Pictures 和 Paramount Pictures兩家公司

對比兩家公司分析數據,從電影產量上來看,Universal Pictures 比Paramount Pictures產量多一些,從多年的利潤變化來看,Universal Pictures 的相對穩定些。

代碼部分如下:

movie_credit[production_companies] = movie_credit[production_companies].str.split(,)com_list = []for x in movie_credit[production_companies]: com_list.extend(x)companies = pd.Series(com_list).value_counts().sort_values(ascending = True)c1 = companies[[Universal Pictures, Paramount Pictures]]revenue = movie_credit[revenue].groupby(movie_credit[release_year]).sum()#繪製兩家公司電影數量對比圖ax = c1.plot.bar(width_=0.3)plt.xticks(fontsize=15 ,rotation = 0)plt.yticks(fontsize=15)plt.ylabel(數量, fontsize = 15)plt.grid(True)ax.patches[0].set_facecolor(firebrick)plt.title(兩家公司電影數量對比, fontsize = 16)plt.show()# 建立 新的數據框,new_companies,budget, revenue,relase_yearnew_df= movie_credit[[new_companies,budget,revenue,release_year]].reset_index(drop=True)new_df.index = movie_credit[release_year]# 從字元串中篩選出,兩家公司Universal_Pictures,Paramount_Picturesnew_df[Universal_Pictures] = new_df[new_companies].str.contains(Universal Pictures).apply(lambda x:1 if x else 0)new_df[Paramount_Pictures] = new_df[new_companies].str.contains(Paramount Pictures).apply(lambda x:1 if x else 0)#加入利潤一列new_df[profit] = new_df[revenue] - new_df[budget]#將Universal_Pictures,Paramount_Pictures 的利潤提取出來,並通過groupby合併每年的總利潤new_df[Universal_Pictures_profit]=new_df[profit]*new_df[Universal_Pictures]new_df[Paramount_Pictures_profit] =new_df[profit]*new_df[Paramount_Pictures]company1 = new_df[Universal_Pictures_profit].groupby(release_year).sum()company2 = new_df[Paramount_Pictures_profit].groupby(release_year).sum()#繪製兩家公司的總利潤隨時間變化折線圖fg = plt.figure(figsize=(10,8))ax1 = fg.add_subplot(1,1,1)company1.plot(x =new_df.index, y = Universal_Pictures_profit, label = Universal_Pictures, ax = ax1)company2.plot(x =new_df.index, y = Paramount_Pictures_profit, label = Paramount_Pictures, ax = ax1)plt.title(每年的總利潤, fontsize = 16)plt.xticks(fontsize = 14)plt.yticks(fontsize = 14)plt.xlabel(Year, fontsize =16)plt.ylabel(利潤, fontsize =16)plt.legend(fontsize = 13)plt.show()

  • 我們如何通過導演判斷電影是否值得看?

去影院,選擇高票房,高評分的導演拍出的電影,是一個不錯的選擇,上面篩選出來10位導演,選擇他們派出來的電影是一個不錯的選擇。

代碼部分如下:

#評分和票房高的電影的導演排行top_votes =movie_credit[movie_credit[vote_average] >=8].sort_values(by = vote_average, ascending = False)top_votes[top_votes.isnull()]#刪除空值top_votes = top_votes[[ director, vote_average , revenue]].dropna()top_revenue = top_votes.sort_values(by = revenue, ascending = False)top_revenue = top_revenue[[ revenue,director]]top_revenue1 = top_revenue.groupby(director)[revenue].mean().sort_values(ascending = True)# 圖表可視化plt.figure(figsize = (15,5))plt.subplot(1,2,1)ax1 =top_revenue1.tail(10).plot.barh(width_=0.8,color = #228B22)plt.xticks(fontsize=13 ,rotation = 0)plt.yticks(fontsize=13)plt.xlabel(票房,fontsize = 13)plt.ylabel(導演, fontsize = 13)plt.grid(True)plt.title(高票房高評分導演排行榜, fontsize = 15)

  • 從哪些熱度詞中,能否判斷觀眾偏好?

從詞雲中發現出現熱度辭彙,independent(獨立),woman(女性),relitionship(關係),謀殺(Murder)等,我們可以了解大眾的關注的熱點,了解觀眾的偏好。

代碼部分如下:

#讀入背景圖片 pic_mask = np.array(Image.open(D:python#TMDB電影數據可視化地圖.jpg))#讀取生成詞雲的文件或字元串wordlist = []for word in new1_df[keywords]: wordlist.append(word)wordstr = .join(wordlist)plt.figure(figsize= (10,8))# 設置停用詞stopwords = set(STOPWORDS)stopwords.add(film)my_wordcloud =WordCloud( background_color = black,# 設置背景顏色 mask = pic_mask, # 設置背景圖片 stopwords = stopwords, # 設置停用詞 max_words = 200,# 設置最大現實的字數 max_font_size = 60 ,# 設置字體最大值 scale =1, random_state = 30 # 設置有多少種隨機生成狀態,即有多少種配色方案 )my_wordcloud.generate(wordstr)image_colors = ImageColorGenerator(pic_mask)plt.imshow(my_wordcloud)plt.axis(off)plt.show()

最後,歡迎大家一起交流,學習。

推薦閱讀:

聲音信號處理的筆記
R語言實戰—04數據基本管理
數據科學的新生代工具(附實操代碼)
「數據摺疊」:人工智慧背後的人工
數據時代

TAG:數據分析 | 大數據 | 數據 |