當我們談論電影時...4000部電影的可視化分析,Python練習

從kaggle上下載TMDB(著名電影信息提供商)數據,橫跨80多年4000+部電影【下載地址】

想探索「什麼樣的電影市場好「,可以從以下方面分析:

  • 最近幾年電影類型變化?
  • 製作成本最高的是什麼類型電影?
  • 成本預算和票房、收益有關嗎?
  • 原創電影、改編電影比例如何?
  • 票房受上映月份影響嗎?
  • 不同年代電影題材偏好的變化?

解決這些問題,並用可視化展示。


1、數據預處理

原始數據有兩個表,一張電影信息表movies,包含片名、製作成本、票房之類的,一張演職員表credits。

發現movies表的id和credits表的movie_id是對應的,把它們連起來再說:

joint = pd.concat([movies,credits], axis=1)joint.info()

joint里現在有24個變數,準備只保留有意義的。帶 * 的是json類型,等下要特別處理。

另外,可以看到所選欄位的缺失值都非常少,不影響整體,所以~...就直接刪除了缺失值。

joint=joint.drop([homepage,original_language,status,tagline,movie_id,title],axis=1)joint=joint.dropna(how=any,axis=0)

得到4799條完整數據。

接下來處理json類型的欄位。

import json#定義json格式的欄位集json_col = [genres,keywords,production_companies, production_countries,cast,crew]#將欄位解碼成Python數據類型for i in json_col: joint[i] = joint[i].apply(json.loads)

選一個欄位看看解碼後的格式,原來是由字典組成的list,要找的內容在name里,那就提取每個字典的name值~

#獲取name的值用」,「連接def get_names(x): return ,.join([i[name] for i in x])#對每個json類型的欄位都這樣處理for n in json_col: joint[n] = joint[n].apply(get_names)

處理好後的樣子

處理日期,提取上映年份和月份

joint[release_year] = pd.to_datetime(joint[release_date],format=%Y-%m-%d).dt.yearjoint[release_month] = pd.to_datetime(joint[release_date],format=%Y-%m-%d).dt.monthjoint = joint.drop([release_date,spoken_languages],axis=1)

處理異常值,主要是評分、時長為0的用均值替換

joint[budget] = joint[budget].replace(0,joint.budget.mean())joint[revenue] = joint[revenue].replace(0,joint.revenue.mean())joint[runtime] = joint[runtime].replace(0,joint.runtime.mean())joint[vote_average] = joint[vote_average].replace(0,joint.vote_average.mean())

2、可視化分析

2.1 構築各年的影片類型表

#先獲得所有的影片類型genres_list = set()for i in joint.genres.str.split(,): genres_list = set().union(i,genres_list)genres_list = list(genres_list)genres_list.remove()genres_list#默認的整型索引genres_df = joint[[release_year,release_month,original_title]].reset_index(drop = True)for genre in genres_list: #電影類型虛擬變數化 genres_df[genre] = joint[genres].str.contains(genre).apply(lambda x:1 if x else 0) #計算各年各類型電影數量genres_year = genres_df.groupby(release_year).sum()#畫圖plt.figure(figsize=(18,10))plt.plot(genres_year[-25:-1])plt.title(genres change over years,fontsize=18)plt.legend(genres_year)plt.show()

所有年份的,90年代起直線增長

過去25年的

電影產業在90年代迎來極速增長的黃金期,1990-2000十年間翻了近5倍,至今波動上升中~

plt.figure(figsize=(18,10))plt.plot(genres_year[-25:-1])plt.title(genres change over years,fontsize=18)plt.legend(genres_year)plt.show()

堆積圖

柱型堆積圖更直觀地展示影片類型分布。

可以看到過去25年影片結構是非常相似的,說明某些類型具有長期的優勢,這很有趣。占絕對優勢的影片依次是1、Drama,2、Comedy,3、Action、Advanture、Thriller、Romance(懷疑2016起的數據已經不全了,17年的我刪了)。

為了更清晰可以把非常小眾的Foreign、Western、TV Movie等合併為」other「試試,圖例也會清楚一些。

稍微清楚一丟丟。。

2.2 構築每類電影的收益評分表

per_genre_df = pd.DataFrame(index=genres_list)budget_list = [] * len(genres_list)revenue_list = [] * len(genres_list)profit_list = [] * len(genres_list)vote_list = [] * len(genres_list)#評分取中位數,預算、票房、收益取平均數for genre in genres_list: budget_list.append(joint[(joint[genre]==1)].budget.mean()) revenue_list.append(joint[(joint[genre]==1)].revenue.mean()) profit_list.append(joint[(joint[genre]==1)].profit.mean()) vote_list.append(joint[(joint[genre]==1)].vote_average.median()) per_genre_df[mean_budget] = budget_listper_genre_df[mean_revenue] = revenue_listper_genre_df[mean_profit] = profit_listper_genre_df[median_vote] = vote_list#畫圖:以mean_budget為例,其他略data1 = per_genre_df.mean_budget.sort_values(ascending = False)[:10]fig = plt.figure(figsize=(16,10))ax1 = fig.add_subplot(221)data1.plot(kind=bar, ax=ax1)ax1.set_title(mean_budget, size=16)ax1.set_ylim([2e7,9e7])

」動畫/冒險/奇幻「是製作最昂貴的電影類型,第二檔是」科幻/動作/家庭「,這六類電影也是票房和收益的top6。看來砸錢多的電影票房收益也更高。

雖然成本、票房、收益的前六名相同,但圖1可以看出成本是分檔的,而圖2票房和圖3收益卻呈明顯的階梯狀,說明成本接近的電影類型,收益率還是有區別的

想要將票房和成本的關係量化——

散點圖與相關係數表現還行,用線性回歸擬合試試:

from sklearn.cross_validation import train_test_splitx_train, x_test, y_train, y_test = train_test_split(joint.budget , joint.revenue, train_size = .8)x_train = x_train.values.reshape(-1,1)x_test = x_test.values.reshape(-1,1)from sklearn.linear_model import LinearRegressionmodel = LinearRegression()model.fit(x_train,y_train)print(回歸模型:revenue = budget *%.2f+ %.2f %(model.coef_,model.intercept_ ))print(模型準確率:%.2f %(model.score(x_test,y_test)))

回歸模型:revenue = budget *2.85+ 6899490.75

模型準確率:0.51,準確率剛過半,看來希望利潤和成本一個量級不是那麼容易的事。

2 .3 提取原創電影關鍵詞

#非原創電影keywords里有『based on novel』joint[original] = joint[keywords].str.contains(based on novel).apply(lambda x:0 if x else 1)joint[not original] = joint[keywords].str.contains(based on novel).apply(lambda x:1 if x else 0)ori = joint.groupby(release_year).sum()ori = ori[[original,not original]]percent = pd.Series([joint[original].sum(),joint[not original].sum()])#畫圖f,ax = plt.subplots(1,2,figsize=(10,5))ori.plot(ax=ax[0],)percent.plot(kind=pie,labels=[original,not original],autopct=%1.1f%%)

原創電影數量上碾壓改編電影,改編電影是近年來才有上升的。

2.4 票房與月份

每年的6月都想住進電影院... 上映的影片多,票房最高。

2.5 不同年代的電影關鍵詞

從關鍵片語成的詞雲中,看出一個時代的秘密——「當我們談論電影時,我們在談論什麼」。甚至覺得這是分析里最有意思的部分,這裡是用WordArt網站做的。

1912-1950

50年代前,電影最大的主題是「音樂」與「愛」,儘管這段時間的電影產量與後來相比是十分微茫的。注意到悲觀色彩的「noir」、「war」似乎是種暗示。

1950-1990

第二次世界大戰結束,最醒目的關鍵詞「war「赫然立在腦海,痛苦絕望的」violence「、」death「、」loss「雖然還在徘徊,可幸象徵希望的」new「、」love「、」music「比它們更強大。

1990-2005

上面分析過,90年代起電影進入了黃金期,因此獨立電影(independent)得到關注。人們從戰爭中痊癒,電影探討的主題」以人為本「,」relationship「、」love「、」life「、」woman「都是它的反映。

2005-2016

這段時間最大的不同是出現了明顯的」base「、」novel「,證明改編自小說的電影開始成為一種新潮。」女性「、」導演「也得到了很大的關注,彷彿反映出時下社會」追求平等「的氛圍。


用Python畫圖並不熟悉,這次可視化練習給我的感悟是每個工具都有優點,有時候Excel也夠用了。得到清洗好的數據後,用最適合或方便的工具去實現吧,更重要的在於選擇分析維度和展現方式。


推薦閱讀:

電影《七宗罪》的懲罰都是什麼?
怎麼評價《烽火芳菲》?
廢土電影與災難電影區別在哪?
海上鋼琴師怎麼有水平的鑒賞?
《美人宜修》大結局是什麼?

TAG:Python | 可視化 | 電影 |