1. 程式人生 > >國產爛片深度揭祕

國產爛片深度揭祕

 

 

1.讀取資料 

1、讀取資料,以“豆瓣評分”為標準,看看電影評分分佈,及爛片情況
要求:
① 讀取資料“moviedata.xlsx”
② 檢視“豆瓣評分”資料分佈,繪製直方圖、箱型圖
③ 判斷“豆瓣評”資料是否符合正態分佈
④ 如果符合正態分佈,這裡以上四分位數(該樣本中所有數值由小到大排列後第25%的數字)評分為“爛片標準”
⑤ 篩選出爛片資料,並做排名,找到TOP20
提示:
① 讀取資料之後去除缺失值
② 這裡可以用ks檢驗來判斷資料是否符合正態分佈

爛片評價標準:4.3分,整理後爛片資料大概546條

import numpy as np
import
pandas 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)