點贊再看,養成好習慣
Python版本3.8.0,開發工具:Pycharm
寫在前面的話:
如果你是因爲看到標題進來的,那恭喜你,又多了一個漲(入)知(坑)識
的機會。
在這篇豆瓣電影Top250的分析文章中,你並不會得到一個像標題那樣確切的答案
。
但是你可以因此否定很多看似正確的答案,比如下面這些:
“豆瓣電影Top250是根據評分排序的?”
“難道是根據評論數排序?”
“那一定是評分和評論數兩者一起影響的?”
以上的想法或許你曾經也想過,但是都不對。
“爲什麼不對?”
“懷疑我!那我今天就給你分析一下爲什麼!”
數據來源上一節:
不想運行代碼,只想要數據
,行!文末
有數據獲取方式。
另外,和上篇一樣,重點是分析的流程
(敲黑板了)
下面,開始今天的——豆瓣電影分析之路。
假設
“小一哥,怎麼一上來就是假設?假設又是什麼?”
“假設,是針對我們的分析結果而言。你希望最後輸出一個什麼結果,或者你需要證明什麼結果,都可以當做假設!”
數據分析是由結果導向
的,什麼是結果導向?
說白了,其實是根據目的去完成任務
。
你經歷什麼學到什麼,是你自己的經驗教訓,領導不關心,其他人也不關心。你工作是否合格業績、是否優秀,要看結果論成敗。
根據目的去完成任務,總是會事半功倍。你可以用分析去研究你想要的結果
就像週末有朋友要請小一我喫超過兩百塊的大餐,這就是假設。根據假設小一可以選擇去喫什麼,像什麼海底撈、烤全羊統統可以安排,海鮮大餐什麼的也可以啊,那個說喫沙縣的你過分了昂。
但我們的假設可不像兩百塊一樣,是一個定數。我們的假設可能是一個範圍
,一個問題
,或者一個未知的點
。
那對應於這次的分析,我們的假設可以是:
- 哪個星級評分更能體現影片整體評分?
- 影片整體評分與評論數相關嗎?
- 影片整體評分與哪些指標相關?
以上三個問題,你們可以先思考
一下,然後再繼續下一節
數據分析法則
可能你在入門數據分析的時候周圍的人會告訴你帕累托法則
,這個法則最開始是用來形容人類社會的財富分佈:百分之二十的人掌握有百分之八十的財富。
但是現在似乎已經普遍適用,大家都已經認識到:重要的因子通常只佔少數
。
“小一哥,根據帕累托法則,哪個環節最重要?”
“這個就不能用帕累托法則了,數據的重要性毋庸置疑!”
在整個數據分析的週期中,數據清洗直接決定分析結果是否準確
,可視化可以發現事實問題
,並尋找出現的原因
,在數據探索中你可以進行更深層次的數據挖掘
。
數據分析大家現在有個概念就好了,後面會補充一節數據分析的理論知識
數據清洗
“小一哥,數據清洗之前,我們需要先了解什麼?”
“做事之前,肯定要先了解目的啊”
數據清洗的目的是爲了清洗髒數據
,爲後期的數據可視化、特徵工程,保證數據的合理性、準確性
。
“嗷,就是我數據必須得乾淨,不能有錯的”
“不止這些,當你的數據存在異常值,你可能還需要藉助可視化圖表對數據進行異常值檢測”
舉個例子,你的數據中存在年齡字段的時候,你不能只認爲不是整數的就是髒數據。年齡小於0的,大於150的,都需要注意
本次數據因爲髒數據不多,大家理解概念即可,具體清洗方法會補充在理論知識那一節。
準備好了嗎
拿到數據之後,需要先檢查數據的整體缺失情況
''' 1. 查看整體數據類型與缺失情況'''
df_data.info()
可以看到,豆瓣電影 Top250 的數據缺失情況如下:
Data columns (total 21 columns):
id 250 non-null int64
movie_rank 250 non-null object
movie_name 250 non-null object
movie_director 250 non-null object
movie_writer 250 non-null object
movie_starring 250 non-null object
movie_type 250 non-null object
movie_country 250 non-null object
movie_language 250 non-null object
movie_release_date 250 non-null object
movie_run_time 250 non-null object
movie_second_name 2 non-null object
movie_imdb_href 250 non-null object
movie_rating 250 non-null object
movie_comments_user 250 non-null object
movie_five_star_ratio 250 non-null object
movie_four_star_ratio 250 non-null object
movie_three_star_ratio 250 non-null object
movie_two_star_ratio 250 non-null object
movie_one_star_ratio 250 non-null object
movie_note 250 non-null object
“小一哥,這個能看出什麼呢?”
“整體數據字段,以及每個字段的缺失情況!”
可以看到,我們的數據集共有21個字段
,其中只有電影又名字段
有兩個空數據。
我們爬取的豆瓣電影 Top250 數據本就規整,所有沒有缺失屬於正常情況,後面實戰的其他數據可能就沒有這麼規整了。
對於部分影片缺失又名信息,用影片名稱去填充即可
# 用影片名稱填充影片又名字段
df_data['movie_second_name'].fillna(df_data['movie_name'],inplace=True)
帶着整體數據的統計情況,我們去檢查每一個字段
''' 2. 查看單個指標的數據,並進行相應的清洗操作'''
首先是影片排序數據:
# 1. 影片排名數據
df_data['movie_rank'].head(5)
0 No.1
1 No.2
2 No.3
3 No.4
4 No.5
Name: movie_rank, dtype: object
可以看到數據形式是 No.XX
類型,若是建模的話,這種數據類型是不符合要求。
這裏我們將 No.XX 數據的 No. 刪掉,只保留後面的數字
即可。
df_data['movie_rank'] = df_data['movie_rank'].str.replace('No.', '').astype(int)
接下來是影片類型字段:
# 2. 影片類型
df_data['movie_type'].head(5)
0 劇情/犯罪
1 劇情/愛情/同性
2 劇情/愛情
3 劇情/動作/犯罪
4 劇情/喜劇/愛情/戰爭
Name: movie_type, dtype: object
可以看到數據形式是 xx/xx/xx 的形式,數據規整,不需要處理,若是建模的話可以對其進行獨熱編碼
。
接下來是影片製作國家/地區字段:
# 3. 影片製作國家
print(df_data['movie_country'].head(10))
0 美國
1 中國大陸 / 中國香港
2 美國
3 法國
4 意大利
Name: movie_country, dtype: object
可以看到數據形式是 xx / xx 的形式, 用 / 分割,數據規整,但因爲存在空格,需要對空格進行處理。
“這個簡單,小一哥,我會!”
# 這裏直接對空格進行替換
df_data['movie_country'] = df_data['movie_country'].str.replace(' ', '')
“學以致用,很不錯,小夥子!”
接下來是影片語言字段:
和影片製作國家字段一樣,存在空白字符,同樣的處理
方法。
# 同理,直接對空格進行替換
df_data['movie_language'] = df_data['movie_language'].str.replace(' ', '')
接下來是影片上映日期:
# 5. 影片上映日期
df_data['movie_release_date'].head(5)
0 1994-09-10(多倫多電影節)/1994-10-14(美國)
1 1993-01-01(中國香港)/1993-07-26(中國大陸)
2 1994-06-23(洛杉磯首映)/1994-07-06(美國)
3 1994-09-14(法國)
4 1997-12-20(意大利)
Name: movie_release_date, dtype: object
可以看到部分影片存在多個上映日期和上映城市。
“小一哥,這個怎麼處理?有多個上映日期和上映城市”
“這裏只保留首映日期
,日期保留年份即可,並新增
一列上映城市”
df_data['movie_release_date'] = df_data['movie_release_date'].apply(lambda e: re.split(r'/', e)[0])
df_data['movie_release_city'] = df_data['movie_release_date'].apply(lambda e: e[11:-1])
df_data['movie_release_date'] = df_data['movie_release_date'].apply(lambda e: e[:4])
接下來是影片片長:
# 6. 影片片長
df_data['movie_run_time'].head(10))
0 142分鐘
1 171 分鐘
2 142分鐘
3 110分鐘(劇場版)
4 116分鐘
Name: movie_run_time, dtype: object
可以看到影片片長爲 XX分鐘 這種形式,還有部分是 110分鐘(劇場版)這種形式
這裏直接保留影片分鐘數
即可
df_data['movie_run_time'] = df_data['movie_run_time'].apply(lambda e: re.findall(r'\d+', e)[0]).astype(int)
接下來是影片總評分,影片評論數:
# 7. 影片總評分,影片評論人數
df_data[['movie_rating', 'movie_comments_user']].head(5)
設置爲相應的數據格式即可,影片總評分是浮點類型,影片評論數是整數型
# 這裏將影片總評分轉換爲 float、影評人數轉換爲 int(默認都是 object類型)
df_data['movie_rating'] = df_data['movie_rating'].astype(float)
df_data['movie_comments_user'] = df_data['movie_comments_user'].astype(int)
接下來是影片星級評分佔比:
# 8. 影片星級評分佔比
df_data[['movie_five_star_ratio', 'movie_four_star_ratio', 'movie_three_star_ratio',
'movie_two_star_ratio', 'movie_one_star_ratio']].head(5)
可以看出星級評分佔比爲 xx% 的形式。
這裏對所有星級的影片進行處理,將百分比轉換成小數
即可。
“小一哥,數據清洗算是完成了嗎?”
“前面的步驟只是爲了我們可以更好的進行數據可視化。在接下來的可視化過程中,我們會針對性的進行數據清洗”
所以,接下來的,重點(第二次敲黑板
)
數據可視化
通過對數據可視化
,發現數據的分佈
情況,甚至是數據之間的關聯
信息。
”可視化需要用到什麼模塊?
可視化可以使用 matplotlib, 但是我使用了 seaborn。
“爲什麼使用 seaborn 作圖?“
seaborn
同matplotlib
一樣,也是 Python 進行數據可視化分析的重要第三方包。但
seaborn
是在matplotlib
的基礎上進行了更高級的 API 封裝,使得作圖更容易,圖形更漂亮。針對一些特殊情況,還是需要用到
matplotlib
的,應該把seaborn
視爲matplotlib
的補充,而不是替代物。
seaborn 的相關操作大家能看懂即可,後期會抽空出簡單使用教程。
準備好了嗎
上一步中我們已經針對每個字段進行了初步檢測。看一下整體數據的描述性統計:
對數值型特徵進行簡單的描述性統計,包括均值,中位數,衆數,方差,標準差,最大值,最小值等
# 描述性數據統計
df_data.describe()
接下來需要判斷數據類型
,定類?定序?定距?還是定比?
弄清楚這一步主要是爲了後續正確找對方法進行可視化
'''數據類型劃分
影片類型、影片製片國家、影片語言: 定類數據<br>
影片片長、影片總評分、影片評論數、影片時間:定距數據
影片5/4/3/2/1星佔比:定比數據
'''
根據上面對各個特徵數據類型的判斷,選擇合適的可視化方法完成可視化。
定類/定序特徵分析
將影片類型
數據通過 / 分割後統計每個類型出現的次數
'''統計影片類型數據'''
df_data['movie_type'] = df_data['movie_type'].map(lambda e: e.split('/'))
# 將數據轉換成一維數組
movie_type_list = np.concatenate(df_data['movie_type'].values.tolist())
# 將一維數組重新生成 Dataframe 並統計每個類型的個數
movie_type_counter = pd.DataFrame(movie_type_list, columns=['movie_type'])['movie_type'].value_counts()
# 生成柱狀圖的數據 x 和 y
movie_type_x = movie_type_counter.index.tolist()
movie_type_y = movie_type_counter.values.tolist()
畫出影片類型
的柱狀圖
# 畫出影片類型的柱狀圖
ax1 = sns.barplot(x=movie_type_x, y=movie_type_y, palette="Blues_r", )
# Seaborn 需要通過 ax.set_title() 來添加 title
ax1.set_title('豆瓣影片Top250類型統計 by:『知秋小一』')
# 設置 x/y 軸標籤的字體大小和字體顏色
ax1.set_xlabel('影片類型', fontsize=10)
ax1.set_ylabel('類型出現次數', fontsize=10)
# 設置座標軸刻度的字體大小
ax1.tick_params(axis='x', labelsize=8)
# 顯示數據的具體數值
for x, y in zip(range(0, len(movie_type_x)), movie_type_y):
ax1.text(x - 0.3, y + 0.3, '%d' % y, color='black')
plt.show()
後面的畫圖代碼就不一一顯示,整體代碼太長你們看着也不舒服。需要源碼的在文末有獲取方式。
影片類型統計如下:
可以看到,劇情類佔比特別高
,類型前五分別是:劇情、愛情、喜劇、犯罪和冒險
。
其中,還有兩個情色類的,emmm,我就不告訴你們是什麼了。
同理,將影片語言
數據通過 / 分割後統計每個語言出現的次數
影片語言統計如下:
可以看到,英語類佔比特別高
,語言前五分別是:英語、日語、漢語普通話、法語和德語
。
發現一個更有意思的現象,可以看到粵語、上海話、閩南語、重慶話、山西話、湖南話、唐山話、客家話、四川話也都有出現,等會可以看一下具體是哪些影片。
同理將影片製片國家/地區
數據通過 / 分割後統計每個國家/地區出現的次數
影片製片國家統計如下:
好萊塢大國穩居榜首
,製片國家/地區前五分別是美國、日本、英國、中國香港和中國大陸。
港片還是有很多經典之作的,比起大陸來說相對多一些吧。
定距/定比特徵分析
影片片長、影片總評分、影片評論人數都屬於定距定比特徵,我們來依次分析一下。
影片片長統計如下:
影片片長大多在75~175之間,這個也是目前大多數影片的片長。
可以看出還有一個影片在50分鐘以下,難道是個短紀錄片?我們等會把它揪出來瞅瞅
影片總評分統計如下:
影片總評分最高分9.7,最低分8.3,8.8分的最多。
總評分9.4及以上的有十部,不知道是不是對應的 Top10
?
影片評論數統計如下
大部分影片的評論數比較集中,評論數在75w人以下。
評論數最多的接近175w人,可以看出差別還是挺明顯的。
“思考一下,我們前面提起的 帕累托法則(二八原則)
是否適用?”
影片上映日期統計如下:
Top250的影片集中在 2000年~2017年,其中2004年上映影片最多,達到14部。
“請問一個月一部大片是什麼感覺?小一我也想體驗一下!”
影片星級評論佔比統計如下:
影片星級分爲五級,我們來看一下每個星級的評論數
分佈:
星級分佈差別不是很大,但是五星和一星的分佈似乎和總評論數的分佈更符合。
“看來二八原則的適用性還是挺強的!
”
數據探索
上一節我們留下了一些問題,同時還有我們今天的目的:總評分到底與什麼相關?都會在這一節去探索
準備好知道答案了嗎?
先解決上節問題:
影片語言是中國大陸語言的影片:
# 中國大陸參與制作的影片
df_data[df_data['movie_country'].str.contains('中國大陸')][
['movie_rank', 'movie_name', 'movie_release_date',
'movie_type', 'movie_country', 'movie_language']]
影片時長在五十分鐘以下的影片:
df_data.sort_values(by='movie_run_time')[
['movie_rank', 'movie_name', 'movie_release_date', 'movie_run_time',
'movie_rating', 'movie_comments_user']].head(1)
“emmm,是小一我孤陋寡聞了,寫完文章我就去看!”
評論數最多的前五部影片:
# 評論數最多的前五條影片
df_data.sort_values(by='movie_comments_user', ascending=False)[
['movie_rank', 'movie_name', 'movie_release_date', 'movie_rating',
'movie_comments_user']].head(5)
總評論數最多的影片【肖申克的救贖】實至名歸。
但是,豆瓣電影Top250排序真的不是按照評論數排序
的(①)
評分最高的前五部影片
# 評分最高的前五部影片
df_data.sort_values(by='movie_rating', ascending=False)[
['movie_rank', 'movie_name', 'movie_release_date', 'movie_rating',
'movie_comments_user']].head(5)
沒有懸念,總評分最高還是【肖申克的救贖】。
但是,豆瓣電影Top250排序真的不是按照總評分數排序
的(②)
星級評分的前五部電影
我們前面分析出,五星級和一星級分佈與總評分吻合,來看一下
# 五星評分人數最多的前五條影片
df_data['five_star_movie_comments_user'] = \
df_data['movie_comments_user'] * df_data['movie_five_star_ratio']
df_data.sort_values(by='five_star_movie_comments_user', ascending=False)[
['movie_rank', 'movie_name', 'movie_release_date', 'movie_rating',
'movie_comments_user']].head(5)
雖然也不對
,但是似乎比前面兩種的排序靠譜點!(③)
”小一哥,會不會是根據總評分和評論數共同決定排序的?“
”我們來試試“
評分+評論數最高的前五部影片
# 評分+評論數最高的前五部影片
df_data.sort_values(by=['movie_rating', 'movie_comments_user'],
ascending=False)[['movie_rank', 'movie_name', 'movie_release_date',
'movie_rating', 'movie_comments_user']].head(5)
評論數+評分最高的前五部影片
# 評論數+評分最高的前五部影片
df_data.sort_values(by=['movie_comments_user', 'movie_rating'],
ascending=False)[['movie_rank', 'movie_name', 'movie_release_date',
'movie_rating', 'movie_comments_user']].head(5)
豆瓣電影Top250排序也不是按照評論數+總評分排序
的(④)
“還是不對,影片排序不可能是線性這麼簡單的吧,小一哥?”
“是的,影片排序需要用到一種基於用戶投票的排名算法
,類似 IMDB 的加權平均,其中一些影評人,電影人的權重都會考慮進去。“”
關於影片排名算法要說清楚的話可能不是一篇文章能搞定的,而且也脫離
了我們這一片的重點。
豆瓣影片評分算法並未公開,小一我從網上找到的一篇豆瓣影片評分機制的內容,大家瞭解瞭解長個見識
就行了:
豆瓣的註冊用戶看完一部電影,心情好的話會來打個一到五星的分(有時候心情不好也會來)。
比方說一部電影有42萬用戶打分。我們的程序把這42萬個一到五星換算成零到十分,加起來除以42萬,就得到了豆瓣評分。
這個評分會自動出現在豆瓣各處,中間沒有審覈,平時也沒有編輯盯着看。每過若干分鐘,程序會自動重跑一遍,把最新打分的人的意見包括進來。
——豆瓣創始人阿北
總結一下:
提出假設
針對豆瓣電影數據,我們提出了一些小問題
作爲我們分析的目的
數據清洗
檢查數據整體情況,對缺失數據進行增補
,對每個字段的數據檢查是否合理
,並轉換
成我們後期需要的數據。
數據可視化
可視化讓我們對數據有一個直觀的認知,針對不合理數據可以進行二次檢查。
數據探索
解決提出的小問題,針對目標進行深層次的分析。
當然,我們這裏欠缺最後一步:特徵工程和評分模型。(本次分析用不到)
思考
以上就是我們今天分析實戰的主要內容,很基礎
,但是內容也很多,第一個分析項目,旨在讓大家瞭解分析流程
。
覺得今天內容量不夠的同學,也可以思考一下以下幾個問題:
- 還有哪些維度可以互相組合並對總排序造成影響?
- 它們的可視化顯示你能畫出來嗎?
- 評分模型應該怎麼設計(可以參考阮一峯的排名算法)?
源碼獲取
目前爲止,和我們豆瓣電影相關的源碼如下:
在公衆號後臺
回覆 豆瓣電影
獲取 爬取豆瓣電影Top250源碼
在公衆號後臺
回覆 電影數據
獲取 豆瓣電影Top250詳細數據
在公衆號後臺
回覆 電影分析
獲取 分析豆瓣電影Top250源碼
寫在後面的話
第一個實戰項目結束了,有部分內容其實並沒有說清楚,只是直接拿來了用,不知道你們能不能理解。
不過,這兩篇內容都只是我們的一個基礎文章,重點是流程
,不必去細究
其中某個細節。
我已經想好了下一個項目應該玩什麼了,你們準備好了嗎?
下期見
!
碎碎念一下
寫技術文難了不止一個檔次是因爲要把內容輸出成文章,還是挺難的。
我代碼實現兩個晚上就寫完了,但是寫這篇卻用了我
整個週末
的時間,點個贊支持一下
?
原創不易,歡迎點贊噢
文章首發:公衆號【知秋小一】
文章同步:掘金,簡書
原文鏈接:你知道豆瓣電影是怎麼評分的嗎?