國產爛片深度揭祕
1.讀取資料
1、讀取資料,以“豆瓣評分”為標準,看看電影評分分佈,及爛片情況
要求:
① 讀取資料“moviedata.xlsx”
② 檢視“豆瓣評分”資料分佈,繪製直方圖、箱型圖
③ 判斷“豆瓣評”資料是否符合正態分佈
④ 如果符合正態分佈,這裡以上四分位數(該樣本中所有數值由小到大排列後第25%的數字)評分為“爛片標準”
⑤ 篩選出爛片資料,並做排名,找到TOP20
提示:
① 讀取資料之後去除缺失值
② 這裡可以用ks檢驗來判斷資料是否符合正態分佈
爛片評價標準:4.3分,整理後爛片資料大概546條
import numpy as np importpandas as pd import matplotlib.pyplot as plt import warnings warnings.filterwarnings('ignore') # 不發出警告 from bokeh.io import output_notebook output_notebook() # 匯入notebook繪圖模組 from bokeh.plotting import figure,show from bokeh.models import ColumnDataSource,HoverTool # 匯入圖表繪製、圖示展示模組 #匯入ColumnDataSource模組
# 檢視資料,資料清洗 import os os.chdir(r'E:\Python資料分析\專案\11爛片/') # 建立工作路徑 df = pd.read_excel('moviedata.xlsx') df = df[df['豆瓣評分'] > 0] print('初步清洗後資料量為%i條' % len(df)) # 讀取資料 # 刪除“豆瓣評分”小於等於0的值
# 檢視豆瓣評分情況 fig = plt.figure(figsize = (10,6)) plt.subplots_adjust(hspace=0.2) # 建立繪圖空間 ax1 = fig.add_subplot(2,1,1) df['豆瓣評分'].plot.hist(stacked=True,bins=50,color = 'green',alpha=0.5,grid=True) plt.ylim([0,150]) plt.title('豆瓣評分資料分佈-直方圖') # 繪製直方圖 ax2 = fig.add_subplot(2,1,2) color = dict(boxes='DarkGreen', whiskers='DarkOrange', medians='DarkBlue', caps='Gray') df['豆瓣評分'].plot.box(vert=False, grid = True,color = color) plt.title('豆瓣評分資料分佈-箱型圖') # 繪製箱型圖 df['豆瓣評分'].describe()
# 判斷是否符合正態分佈 from scipy import stats # 匯入相關模組 u = df['豆瓣評分'].mean() # 計算均值 std = df['豆瓣評分'].std() # 計算標準差 stats.kstest(df['豆瓣評分'], 'norm', (u, std)) # 這裡p值大於0.05,為正態分佈 # 結論 # 這裡以樣本資料上四分位數為爛片評判標準 → 4.3分
# 篩選出爛片資料,並做排名,找到TOP20 data_lp = df[df['豆瓣評分']<4.3].reset_index() print('資料整理後,得到爛片資料量為%i條' % len(data_lp)) # 篩選爛片資料 lp_top20 = data_lp[['電影名稱','豆瓣評分','導演','主演']].sort_values(by = '豆瓣評分').iloc[:20].reset_index() del lp_top20['index'] lp_top20 # 檢視爛片top20
2、什麼題材的電影爛片最多?
要求:
① 按照“型別”欄位分類,篩選不同電影屬於什麼題材
② 整理資料,按照“題材”彙總,檢視不同題材的爛片比例,並選取TOP20
③ 將得到的題材爛片比例TOP20製作散點圖 → 橫座標為“題材”型別,縱座標為爛片比例,點大小為樣本數量
** 用bokeh製圖
** 按照爛片比例做降序排列
提示:
① 刪除“型別”欄位空值的資料
② 由於一個電影“型別”會有多個,這裡需要將一個電影每個“型別”都識別出來,在統計某個題材時都需要計算,例如:
如果一個電影的型別為:“喜劇/愛情”,則在計算“喜劇”、“愛情”題材的爛片比例時,都需要將該電影算上
③ 注意型別欄位中,要刪除空格字元
④ bokeh圖設定點大小,這裡通過 開方減小資料差距 → size = count**0.5*係數
# 篩選出所有題材型別 typelst = [] for i in df[df['型別'].notnull()]['型別'].str.replace(' ','').str.split('/'): typelst.extend(i) # 取出所有電影的“型別”,並整理成列表 # 注意這裡要刪除“型別”中的空格字元 typelst = list(set(typelst)) print(typelst) # 列表去重
# 建立函式,檢視不同題材的爛片比例 # 這裡要刪除“型別”欄位空值的資料 lst_type_lp = [] # 建立空字典、空列表 df_type = df[df['型別'].notnull()][['電影名稱','豆瓣評分','型別']] # 篩選資料 def f1(data,typei): dic_type_lp = {} datai = data[data['型別'].str.contains(typei)] # 篩選資料 lp_pre_i = len(datai[datai['豆瓣評分']<4.3])/len(datai) # 計算該題材爛片比例 dic_type_lp['typename'] = typei dic_type_lp['typecount'] = len(datai) dic_type_lp['type_lp_pre'] = lp_pre_i # 將結果記錄進字典中,包括題材型別、爛片比例、樣本資料數量 return(dic_type_lp) for i in typelst: dici = f1(df_type,i) lst_type_lp.append(dici) # 按照題材遍歷資料,得到不同題材的爛片比例 df_type_lp = pd.DataFrame(lst_type_lp) type_lp_top20 = df_type_lp.sort_values(by = 'type_lp_pre',ascending = False).iloc[:20] type_lp_top20 # 篩選出爛片比例TOP的題材型別
# bokeh製圖 type_lp_top20['size'] = type_lp_top20['typecount']**0.5*2 # 設定點大小,這裡通過開方減小資料差距 source = ColumnDataSource(data=type_lp_top20) # 建立資料 lst_type = type_lp_top20['typename'].tolist() # 設定橫座標list hover = HoverTool(tooltips=[("資料量", "@typecount"), ("爛片比例","@type_lp_pre")]) # 設定標籤顯示內容 p = figure(x_range=lst_type, plot_width=900, plot_height=350, title="不同電影題材爛片比例", tools=[hover,'reset,xwheel_zoom,pan,crosshair,box_select']) # 構建繪圖空間 p.circle(x='typename',y='type_lp_pre',source = source, size = 'size', line_color = 'black',line_dash = [6,4],fill_color = 'red',fill_alpha = 0.7) # 繪製散點圖 p.xgrid.grid_line_dash = [10,4] p.ygrid.grid_line_dash = [10,4] # 設定其他引數 show(p)
3、和什麼國家合拍更可能產生爛片?
要求:
① 按照“製片國家/地區”欄位分類,篩選不同電影的製片地
② 整理資料,按照“題材”彙總,檢視不同題材的爛片比例,並選取TOP20
提示:
① 刪除“製片國家/地區”欄位空值的資料
② 刪除“製片國家/地區”中不包括“中國大陸”的資料
③ 製片地刪除“中國大陸”、“中國”、“臺灣”、“香港”等噪音資料
④ 篩選合作電影大於等於3部以上的國家
# 篩選電影製片地 # 這裡要刪除“製片國家/地區”欄位空值的資料 # 製片地刪除“中國大陸”、“中國”、“臺灣”、“香港”等噪音資料 df_loc = df[['電影名稱','製片國家/地區','豆瓣評分']][df['製片國家/地區'].notnull()] df_loc = df_loc[df_loc['製片國家/地區'].str.contains('中國大陸')] # 篩選資料 loclst = [] for i in df_loc['製片國家/地區'].str.replace(' ','').str.split('/'): loclst.extend(i) # 取出所有電影的製片地,並整理成列表 # 注意這裡要刪除“製片國家/地區”中的空格字元 loclst = list(set(loclst)) loclst.remove('中國大陸') loclst.remove('中國') loclst.remove('臺灣') loclst.remove('香港') print(loclst) # 列表去重
# 建立函式,檢視不同製片地的爛片比例 lst_loc_lp = [] # 建立空列表 def f2(data,loci): dic_loc_lp = {} datai = data[data['製片國家/地區'].str.contains(loci)] # 篩選資料 lp_pre_i = len(datai[datai['豆瓣評分']<4.3])/len(datai) # 計算該製片地爛片比例 dic_loc_lp['loc'] = loci dic_loc_lp['loccount'] = len(datai) dic_loc_lp['loc_lp_pre'] = lp_pre_i # 將結果記錄進字典中,包括製片地、爛片比例、樣本資料數量 return(dic_loc_lp) for i in loclst: dici = f2(df_loc,i) lst_loc_lp.append(dici) # 按照題材遍歷資料,得到不同製片地的爛片比例 df_loc_lp = pd.DataFrame(lst_loc_lp) df_loc_lp = df_loc_lp[df_loc_lp['loccount']>=3] # 篩選合作電影大於等於3部以上的國家 loc_lp_top20 = df_loc_lp.sort_values(by = 'loc_lp_pre',ascending = False).iloc[:20] loc_lp_top20 # 篩選出爛片比例TOP的製片地 # 結論 # 綜合來看,居然和歐美合作更可能產生爛片
4、卡司數量是否和爛片有關?
要求:
① 計算每部電影的主演人數
② 按照主演人數分類,並統計爛片率
** 分類:'1-2人','3-4人','5-6人','7-9人','10以上'
③ 檢視爛片比例最高的演員TOP20
提示:
① 通過“主演”欄位內做分列來計算主演人數
② 需要分別統計不同主演人數的電影數量及爛片數量,再計算爛片比例
③ 這裡可以按照明星再檢視一下他們的爛片率,比如:吳亦凡、楊冪、黃曉明、甄子丹、劉亦菲、范冰冰....
# 計算每部電影的主演人數,並統計爛片率 # 分類:'1-2人','3-4人','5-6人','7-9人','10以上' df['主演人數'] = df['主演'].str.split('/').str.len() # 計算主演人數 df_leadrole1 = df[['主演人數','豆瓣評分']].groupby('主演人數').count() df_leadrole2 = df[['主演人數','豆瓣評分']][df['豆瓣評分']<4.3].groupby('主演人數').count() # 按照主演人數分組,分別統計電影數量及爛片數量 df_leadrole_pre = pd.merge(df_leadrole1,df_leadrole2,left_index = True,right_index = True) df_leadrole_pre.columns = ['電影數量','爛片數量'] # 按照主演人數統計爛片比例 df_leadrole_pre.reset_index(inplace = True) df_leadrole_pre['主演人數分類'] = pd.cut(df_leadrole_pre['主演人數'], [0,2,4,6,9,50], labels = ['1-2人','3-4人','5-6人','7-9人','10人及以上']) df_leadrole_pre2 = df_leadrole_pre[['主演人數分類','電影數量','爛片數量']].groupby('主演人數分類').sum() df_leadrole_pre2['爛片比例'] = df_leadrole_pre2['爛片數量']/df_leadrole_pre2['電影數量'] df_leadrole_pre2 # 按照主演人數分類後再統計 # 分類:'1-2人','3-4人','5-6人','7-9人','10以上'
# 篩選主演 # 這裡用爛片資料來篩選,不用全資料 df_role1 = df[(df['豆瓣評分']<4.3) & (df['主演'].notnull())] df_role2 = df[df['主演'].notnull()] leadrolelst = [] for i in df_role1['主演'][df_role1['主演'].notnull()].str.replace(' ','').str.split('/'): leadrolelst.extend(i) # 取出所有電影的主演,並整理成列表 # 注意這裡要刪除“主演”中的空格字元 leadrolelst = list(set(leadrolelst)) print('篩選後的主演演員人數為%i人' % len(leadrolelst)) print(leadrolelst) # 列表去重
# 檢視不同主演的爛片比例 # 這裡去除掉拍過3次電影以下的演員 lst_role_lp = [] # 建立空字典、空列表 for i in leadrolelst: datai = df_role2[df_role2['主演'].str.contains(i)] if len(datai) >2: dic_role_lp = {} lp_pre_i = len(datai[datai['豆瓣評分']<4.3])/len(datai) # 計算該主演爛片比例 dic_role_lp['role'] = i dic_role_lp['rolecount'] = len(datai) dic_role_lp['role_lp_pre'] = lp_pre_i lst_role_lp.append(dic_role_lp) # 按照題材遍歷資料,得到不同主演的爛片比例 df_role_lp = pd.DataFrame(lst_role_lp) role_lp_top20 = df_role_lp.sort_values(by = 'role_lp_pre',ascending = False).iloc[:20] role_lp_top20 # 篩選出爛片比例TOP20的演員
# 檢視特定演員的爛片率 print(df_role_lp[df_role_lp['role'] == '吳亦凡']) df_role2[['電影名稱','主演','豆瓣評分']][df_role2['主演'].str.contains('吳亦凡')]
5、不同導演每年電影產量情況是如何的?
要求:
① 通過“上映日期”篩選出每個電影的上映年份
② 檢視不同導演的爛片比例、這裡去除掉拍過10次電影以下的導演
③ 檢視不同導演每年的電影產量製作散點圖 → 橫座標為年份,縱座標為每年電影平均分,點大小該年電影數量
** 用bokeh製圖
** 橫座標限定為2007-2017年
** 繪製散點圖只需要用產出過爛片的導演資料
提示:
① 注意要刪除“上映日期”中的空格字元
② 繪製圖表時,分開建立資料繪製
# 電影“上映日期”欄位整理 → 時間序列 # 注意這裡要刪除“上映日期”中的空格字元 # 年份限定為2007-2017年 df_year = df[['電影名稱','導演','豆瓣評分','上映日期']][df['導演'].notnull()] df_year = df_year[df_year['上映日期'].notnull()] df_year['上映日期'] = df_year['上映日期'].str.replace(' ','') # 刪除空格字元 df_year['year'] = df_year['上映日期'].str[:4] # 識別年份 df_year = df_year[df_year['year'].str[0] == '2'] # 去除錯誤資料 df_year['year'] = df_year['year'].astype(np.int) # 年份設定為整型 df_year.head()
# 篩選導演 directorlst = [] for i in df_year['導演'].str.replace(' ','').str.split('/'): directorlst.extend(i) # 取出所有電影的主演,並整理成列表 # 注意這裡要刪除“主演”中的空格字元 directorlst = list(set(directorlst)) print('篩選後的導演人數為%i人' % len(directorlst)) print(directorlst) # 列表去重
# 檢視不同導演的爛片比例 # 這裡去除掉拍過10次電影以下的導演 # 年份限定為2007-2017年 lst_dir_lp = [] # 建立空字典、空列表 for i in directorlst: datai = df_year[df_year['導演'].str.contains(i)] if len(datai) >10: dic_dir_lp = {} lp_pre_i = len(datai[datai['豆瓣評分']<4.3])/len(datai) # 計算該主演爛片比例 dic_dir_lp['dir'] = i dic_dir_lp['dircount'] = len(datai) dic_dir_lp['dir_lp_pre'] = lp_pre_i lst_dir_lp.append(dic_dir_lp) # 按照題材遍歷資料,得到不同主演的爛片比例 df_dir_lp = pd.DataFrame(lst_dir_lp) df_dir_lp # 檢視爛片比例
# 計算不同導演每年的電影產量及電影均分 # 這裡只看產出過爛片的導演資料 def f3(data,diri): datai = data[data['導演'].str.contains(diri)] # 篩選資料 data_moviecount = datai[['year','電影名稱']].groupby('year').count() data_scoremean = datai[['year','豆瓣評分']].groupby('year').mean() df_i = pd.merge(data_moviecount,data_scoremean,left_index = True,right_index = True) df_i.columns = ['count','score'] df_i['size'] = df_i['count']*5 return(df_i) dirdata1 = f3(df_year,'王晶') dirdata2 = f3(df_year,'周偉') dirdata3 = f3(df_year,'徐克') dirdata4 = f3(df_year,'鄧衍成') # 分別得到不同導演的資料 dirdata1
# bokeh製圖 from bokeh.models.annotations import BoxAnnotation # 匯入BoxAnnotation模組 hover = HoverTool(tooltips=[("該年電影均分", "@score"), ("該年電影產量","@count")]) # 設定標籤顯示內容 p = figure(plot_width=900, plot_height=500, title="不同導演每年的電影產量及電影均分", tools=[hover,'reset,xwheel_zoom,pan,crosshair,box_select']) # 構建繪圖空間 source1 = ColumnDataSource(dirdata1) p.circle(x='year',y='score',source = source1,size = 'size',legend="王晶",fill_color = 'olive',fill_alpha = 0.7,line_color = None) # 繪製散點圖1 source2 = ColumnDataSource(dirdata2) p.circle(x='year',y='score',source = source2,size = 'size',legend="周偉",fill_color = 'blue',fill_alpha = 0.7,line_color = None) # 繪製散點圖2 source3 = ColumnDataSource(dirdata3) p.circle(x='year',y='score',source = source3,size = 'size',legend="徐克",fill_color = 'green',fill_alpha = 0.7,line_color = None) # 繪製散點圖3 source4 = ColumnDataSource(dirdata4) p.circle(x='year',y='score',source = source4,size = 'size',legend="鄧衍成",fill_color = 'gray',fill_alpha = 0.7,line_color = None) # 繪製散點圖4 bg = BoxAnnotation(top=4.4,fill_alpha=0.1, fill_color='red') p.add_layout(bg) # 繪製爛片分隔區域 p.xgrid.grid_line_dash = [10,4] p.ygrid.grid_line_dash = [10,4] p.legend.location = "top_right" # 設定其他引數 show(p)