您的位置:首页 > 编程语言 > Python开发

Python 数据分析微专业课程--项目实战10 国产烂片深度揭秘

2018-09-04 21:37 881 查看

1.项目说明

读取电影数据,筛选出烂片数据,从各个角度分析烂片特征

2.项目具体要求

1、读取数据,以“豆瓣评分”为标准,看看电影评分分布,及烂片情况
要求:
① 读取数据“moviedata.xlsx”
② 查看“豆瓣评分”数据分布,绘制直方图、箱型图
③ 判断“豆瓣评”数据是否符合正态分布
④ 如果符合正态分布,这里以上四分位数(该样本中所有数值由小到大排列后第25%的数字)评分为“烂片标准”
⑤ 筛选出烂片数据,并做排名,找到TOP20

2、什么题材的电影烂片最多?
要求:
① 按照“类型”字段分类,筛选不同电影属于什么题材
② 整理数据,按照“题材”汇总,查看不同题材的烂片比例,并选取TOP20
③ 将得到的题材烂片比例TOP20制作散点图 → 横坐标为“题材”类型,纵坐标为烂片比例,点大小为样本数量

3、和什么国家合拍更可能产生烂片?
要求:
① 按照“制片国家/地区”字段分类,筛选不同电影的制片地
② 整理数据,按照“题材”汇总,查看不同题材的烂片比例,并选取TOP20

4、卡司数量是否和烂片有关?
要求:
① 计算每部电影的主演人数
② 按照主演人数分类,并统计烂片率
** 分类:'1-2人','3-4人','5-6人','7-9人','10以上'
③ 查看烂片比例最高的演员TOP20

5、不同导演每年电影产量情况是如何的?
要求:
① 通过“上映日期”筛选出每个电影的上映年份
② 查看不同导演的烂片比例、这里去除掉拍过10次电影以下的导演
③ 查看不同导演每年的电影产量制作散点图 → 横坐标为年份,纵坐标为每年电影平均分,点大小该年电影数量

3.实现思路:

1.项目目的是对国产烂片进行分析,所以首先需要将烂片电影筛选出来,因此需要确定一个烂片的标准。这里可以对电影的豆瓣评分分布
进行正态性检验,如果符合正态分布,将评分小于1/4分位的电影作为烂片。
首先读取数据,并筛选出分析所需字段,去除空值,然后根据豆瓣评分数据绘制直方图、箱型图查看其分布,使用stats.kstest()计算其P值,
若符合正太分布,即可计算1/4分位,作为烂片筛选的标准。

2.根据数据,一部电影可能符合多个类型,多个主要演员,多个导演,多个国家合拍,因此可能需要进行多次的对字段进行拆分并进行纵向连接的操作,
因此可以创建一个函数完成对字段拆分和重新连接。这里分析哪些电影题材烂片较多,可以对'类型'字段使用函数进行拆分连接,按照“题材”对全部数据和烂片分组求和,
汇总计算烂片比例,排序后选取TOP20。对TOP20数据绘制散点图。这样可以清晰的得到各个题材电影的烂片数量和比例。

3.分析合拍片的烂片情况,需要首先对'制片国家/地区'字段进行清洗筛选出合拍片,进行拆分连接,然后根据国家进行分组计数,
分别计算拍片数量和烂片数量,即可知道合拍片中与各个国家产生的烂片情况。

4.分析主演人数与烂片的关系,先对'主演'字段进行拆分,计算每部电影的主演数量,根据数量使用pandas.cut()按照'1-2人','3-4人','5-6人','7-9人','10以上'
进行分类,然后计算每个分类的电影数量和烂片数量,即可知道各个分类的烂片情况。
分析哪些演员的烂片较多,对'主演'字段拆分后进行纵向连接,然后根据主要进行分组计数,分别筛选出电影总数和烂片数,计算烂片占比,
去除电影较少的演员数据,排序后即可得到烂片占比排名。

5.分析导演拍烂片的情况,分两步:第一步:计算各个导演的拍片数据和烂片数据,筛选出烂片较多的几个导演;第二部;对这几个导演的各个年份的影片数据进行分析,
包括电影数量,平均得分等

4.实现过程:

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'D:\IT\python数据分析师\项目11')

#数据读取
data = pd.read_excel('moviedata.xlsx')

#电影数据选取,去除空值
data1 = data[['电影名称','豆瓣评分','导演','主演','类型']]
data1.dropna(inplace = True)

#绘制直方图
data1.hist(figsize = (12,3),color = 'navy',alpha = 0.6,bins = 30,edgecolor = 'black')
plt.xlim([2,10])
plt.grid(linestyle='--')
plt.title('豆瓣评分数据分布-直方图')

#绘制箱型图
data1[['豆瓣评分']].plot.box(vert =False, figsize = (12,3),title = '豆瓣评分数据分布-箱型图')
plt.grid(linestyle = '--')
plt.xlim([2,10])
#导入stats 模块做正太性检验
from scipy import stats

u = data1['豆瓣评分'].mean()  #评分均值
std = data1['豆瓣评分'].std()  #评分标准差
q1 = data1['豆瓣评分'].quantile(q=0.25) #4/1分位
stats.kstest(data1['豆瓣评分'],'norm',(u,std))  #ks检验
print('P值7.146大于0.05,评分数据为正太分布.')

data_lp = data1[data1['豆瓣评分']<q1] #烂片标准为评分低于q1,计算获得烂片数据
data_lp.sort_values(by = '豆瓣评分',inplace = True) #根据评分排序
data_lp.reset_index(drop = True,inplace= True) #重置索引
print('数据整理后,得到烂片数据量为%i条' % len(data_lp))
print(data_lp.head(20))

说明:
分析烂片数据需要首先确定烂片的标准,确定烂片的标准很多,例如根据票房,根据评分,根据排名等等,在这里根据豆瓣评分的分布情况来确定烂片标准,数据的分布特点首先检验其正态性,首先绘制直方图查看数据分布,使用stats.kstest()进行检验,根据P值确定豆瓣评分呈正太分布,因此这里使用4/1分位来划定烂片。再筛选可得到烂片数据。

#创建函数,用于将一个字段做分割,并重新做纵向连接
def f1(data,col):
lst = []
df = data[col].str.split('/',expand =True)
for n in df.columns.tolist():
df
 = df
.str.strip()
lst.append(data.iloc[:,:-1].join(df[
]))
for i in range(len(lst)):
lst[i].columns=data.columns.tolist()
return pd.concat(lst)

from bokeh.models import HoverTool

#电影类型数据处理
data_type = data1[['电影名称','豆瓣评分','类型']]  #筛选出电影类型数据
data_type1 = f1(data_type,'类型').dropna()   #将类型字段分割,再做纵向连接
data_type1.reset_index(inplace = True,drop = True) #重置索引

type_g = data_type1.groupby('类型')[['电影名称']].count()  #根据电影类型分组,获得每个类型的电影数量
type_lp_g = data_type1[data_type1['豆瓣评分']<q1].groupby('类型')[['电影名称']].count() #对烂片电影根据类型分组,获得每个类型烂片数量
type_join = type_g.join(type_lp_g,rsuffix='_lp')  #每个类型电影数量和烂片数量做数据连接
type_join.fillna(0,inplace = True)  #空值填充0
type_join.reset_index(inplace =True) #重置索引
type_join['烂片占比'] = type_join['电影名称_lp']/type_join['电影名称'] #计算每个类型的烂片占比
type_join.columns = ['typename','typecount','lp_count','type_lp_per'] #重新命名字段
type_join.sort_values(by='type_lp_per',ascending=False,inplace =True) #根据占比排序

#绘图数据准备
lp_top = type_join.iloc[:20].reset_index(drop=True) #选取烂片占比前20的类型
print(lp_top)

lp_top['size'] = lp_top['typecount']**0.5 #size 字段
type_list = lp_top['typename'].tolist() #生成电影类型list

#数据生成
source = ColumnDataSource(data=lp_top)

#标签设置
hover = HoverTool(tooltips=[('数据量','@typecount'),
('烂片比例:','@type_lp_per')])

#生成绘图对象
p = figure(x_range =type_list,plot_width = 800,plot_height = 300,title = '不同电影题材烂片比例',tools = [hover,'box_select,wheel_zoom,reset,crosshair'])
#绘制烂片占比散点图
p.circle(x='typename',y='type_lp_per',source = source,size = 'size',color ='red',alpha = 0.6,line_dash=[10,2])
p.grid.grid_line_alpha = 0.6

show(p)

说明:
1. 对字段进行分割再进行连接的逻辑是:首先对需要分割的字段使用s.str.strip()进行分割并将个分割项扩展成字段,生成独立的一个dataframe,然后对将其的每一个字段与原表格进行横向连接,用列表存储,然后用pd.concat()对列表总的数据进行纵向连接即可。
2.这里对电影类型数据的分析首先使用分割链接函数对’类型’字段进行处理,然后根据类型进行分组计数,在筛选出烂片数据进行分组计数,
连接后即可计算得到每个类型的烂片占比情况。根据占比排序后使用bokeh绘制散点图。
3.根据散点图可知:电影市场上喜剧,爱情,动作三种类型的影片数量较多,爱情和喜剧烂片占比相近,动作片烂片相对较少;烂片比例较高的三种类型是:情色,恐怖,惊悚,情色属于小众影片,恐怖和惊悚这种类型片烂片占比较大,特别是惊悚数量较多,烂片占比超过50%.
4.不容易产生烂片的三种类型是犯罪,音乐,战争。

#电影制片国家/地区数据筛选,处理,汇总
data2 = data[['电影名称','豆瓣评分','制片国家/地区']].dropna()  #筛选出国家/地区数据
data2['制片国家/地区']=data2['制片国家/地区'].str.strip() #制片国家/地区字段去除空格
data3 = data2[data2['制片国家/地区'].str.contains('中国大陆')]#删除“制片国家/地区”中不包括“中国大陆”的数据
data3 = data3[data3['制片国家/地区']!='中国大陆'] #删除非合拍片数据

loc_df = f1(data3,'制片国家/地区').dropna() #将“制片国家/地区”做分割并做纵轴连接
loc_df.columns = ['name','score','loc'] #重命名字段

#制片地删除“中国大陆”,“台湾”、“香港”等噪音数据
loc_fgn= loc_df[(loc_df['loc']!='中国大陆')&(loc_df['loc']!='香港')&(loc_df['loc']!='台湾')]
loc_fgn_g = loc_fgn.groupby('loc')[['name']].count() #根制片地进行分组,计算每个国家的制片数量
loc_lp =loc_fgn[loc_fgn['score']<q1] #获得每个制片国家数据中的烂片数据
loc_lp_g = loc_lp.groupby('loc')[['name']].count() #计算每个国家制片的烂片数量

loc_df2 = loc_fgn_g.join(loc_lp_g,rsuffix='_lp') #将每个国家的制片数量和烂片数量连接
loc_df2.columns = ['loccount','lp_count'] #重命名字段
loc_df2['loc_lp_per'] = loc_df2['lp_count']/loc_df2['loccount'] #计算烂片占比
loc_top = loc_df2[loc_df2['loccount']>=3].sort_values(by = 'loc_lp_per',ascending=False) #筛选出拍片数量大于3部的国家或地区,并做降序排序

loc_top = loc_top.fillna(0).reset_index() #空值填充,并重置索引
print(loc_top)

说明:
1.分析合拍片的烂片数据,重点是对筛选合拍片数据,进行处理和汇总,这里合拍片指的是中国大陆与非中国地区的国家和合拍片,所以首先筛选出电影制片国家/地区以及电影名称,评分数据,然后删除不包含’中国大陆’的电影,之后对’电影制片国家/地区’字段进行分割连接,删除“中国大陆”,“台湾”、“香港”等噪音数据,然后根据制片地进行分组汇总,计算影片数量和烂片数量,即可得到合拍片的烂片情况数据。
2.根据数据可知:与中国大陆合拍影片数量较多的国家有四个:美国,韩国,法国,日本,其中与美国合拍产生烂片的比例最高,接近30%

# 计算每部电影的主演人数
#按照主演人数分类,并统计烂片率
#分类:'1-2人','3-4人','5-6人','7-9人','10以上'

#筛选出电影及其主演数据
data_ks = data[['电影名称','豆瓣评分','主演']].dropna()

#计算每部电影的主演数量
zy_df = data_ks['主演'].str.split('/',expand = True)  #分割主演字段
zy_df['主演人数'] = np.nan  #创建'主演人数'的空字段
for i in zy_df.index.tolist():   #循环计算每部电影主演人数
zy_df.loc[i,'主演人数'] = zy_df.loc[i].count()

data_ks['主演人数'] =zy_df['主演人数']  #在电影及主演数据中创建'主演人数字段'

labels =['1-2人','3-4人','5-6人','7-9人','10人及以上']  #分类标签
data_ks['主演人数分类']=pd.cut(data_ks['主演人数'],bins = [0,2,4,6,9,65],labels = labels)  #根据主演人数进行分类

cut_g = data_ks.groupby('主演人数分类')[['电影名称']].count() #根据分类分组,计算每个分类的电影数量
cut_lp_g = data_ks[data_ks['豆瓣评分']<q1].groupby('主演人数分类')[['电影名称']].count() #对烂片数据根据分类分组,计算每个分类的数量
cut_lp_per = cut_g.join(cut_lp_g,rsuffix='_lp')  #分类数据和分类烂片数据连接
cut_lp_per['烂片比例'] = cut_lp_per['电影名称_lp']/cut_lp_per['电影名称'] #计算获得每个分类的烂片占比数据
cut_lp_per.columns=['电影数量','烂片数量','烂片比例'] #重命名字段

print(cut_lp_per)
print('从主演人数分类统计可知主演人数在7-9人烂片比例达到35.44%,\n其次是5-6人比例为25.75%,5-9人的烂片比例超过60%')

#查看烂片比例最高的演员TOP20
data_ks1 = f1(data_ks[['电影名称','豆瓣评分','主演']],'主演') #将主演字段进行分割,并重新进行纵向连接
data_ks1.dropna(inplace = True)  #去除空值

zy_count = data_ks1.groupby('主演')[['电影名称']].count() #根据主演进行分组计算,获得每个演员参演电影的数量
zy_lp_count = data_ks1[data_ks1['豆瓣评分']<q1].groupby('主演')[['电影名称']].count() #根据烂片数据进行分组,得到每个演员的烂片数量
zy_lp_rate = zy_count.join(zy_lp_count,rsuffix="_lp") #演员参演电影数量和烂片数量进行数据连接
zy_lp_rate.dropna(inplace = True)  #去除空值
zy_lp_rate['烂片比例'] = zy_lp_rate['电影名称_lp']/ zy_lp_rate['电影名称'] #计算占比
zy_lp_rate =zy_lp_rate[zy_lp_rate['电影名称']>3] #参演电影数量大于3部的演员
zy_lp_rate = zy_lp_rate.sort_values(by='烂片比例',ascending = False).iloc[:20] #排序,筛选数烂片占比前20的演员
zy_lp_rate.reset_index(inplace = True)  #重置索引
zy_lp_rate.columns = ['actor','count','lp_count','lp_per'] #重命名字段
print(zy_lp_rate)

说明:
1.这里分析电影主演与烂片的关系,从连个方面分析,第一是主演数量,第二是哪些主演烂片最多。主演数量计算首先对’主演’字段进行分割,之后计算每部电影的的主演人数,使用pandas.cut()根据不同人数进行分类,之后就可以根据分类分组统计不同主演人数的影片数量和烂片数量了.
2.根据分析可知:烂片比例最高的人数段是7-9人。
3.分析哪些主演烂片最多,对主演字段进行分割连接,然后根据主演进行分组统计演员的影片数量和烂片数量,之后计算烂片占比,根据占比排序获得top20演员数据。根据结果可知:烂片数量最多的哪些演员都是不知名的N线演员,可能有大部分都是草台班子的剧组的演员。因此,根据演员挑电影还是很重要。

#导入调色盘模块
from bokeh.palettes import BrBG4
from bokeh.transform import factor_cmap

#筛选获得电影及其上映日期,导演数据
data_dy = data[['电影名称','豆瓣评分','上映日期','导演']].dropna() #获取导演数据,删除空值
data_dy['上映日期'] = data_dy['上映日期'].str.strip()  #上映日期字段去除空格
data_dy['year']=data_dy['上映日期'].apply(lambda x: x[:4]) #获得上映年份数据

#年份数据清洗
data_dy = data_dy[(data_dy['year']!= '暂无')&(data_dy['year']!='不详')]
data_dy['year'] = data_dy['year'].astype(int)

#筛选出2007至2017年的数据
data_dy1 = data_dy[(data_dy['year']>=2007)&(data_dy['year']<=2017)]

#分割导演字段并纵向连接
data_dy2 = data_dy1[['电影名称','豆瓣评分','year','导演']]
dy_df = f1(data_dy2,'导演').dropna()

dy_count = dy_df.groupby('导演')[['电影名称']].count() #根据导演进行分组计算,得到每个导演的电影数量
dy_count = dy_count[dy_count['电影名称']>=10] #筛选出大于10部的导演
dy_lp = dy_df[dy_df['豆瓣评分']<q1].groupby('导演')[['电影名称']].count()#对烂片数据根据导演进行分组,得到每个导演的烂片数量
dy_lp_per = dy_count.join(dy_lp,rsuffix="_lp").fillna(0) #导演电影数量和烂片数量连接
dy_lp_per['per'] = dy_lp_per['电影名称_lp']/dy_lp_per['电影名称'] # #烂片占比
dy_lp_per.reset_index(inplace = True)      #重置索引
dy_lp_per.columns = ['dir','dircount','dir_lp_count','dir_lp_per'] #重命名字段
dy_lp_per = dy_lp_per[dy_lp_per['dir_lp_per']>0] #筛选出有烂片的导演数据

#根据上映年份和导演进行分组计算评分均值和计数
dy_g = dy_df.groupby(['year','导演'])[['豆瓣评分']].agg([np.mean,'count']).reset_index()
dy_g1 = pd.merge(dy_g,dy_lp_per,left_on = '导演',right_on='dir').iloc[:,:4] #将数据与烂片占比数据进行连接
dy_g1.columns=['year','dir','score_mean','count'] #重命名字段

dy_g1['size'] = dy_g1['count']*4  #size 字段
year_lst = dy_g1['year'].unique().tolist()  #x轴年份list
dy_lst = dy_g1['dir'].unique().tolist() #导演list,用作图例数据

source = ColumnDataSource(data=dy_g1) #数据生成

#标签设置
hover = HoverTool(tooltips = [('该年电影均分:','@score_mean'),
('改年电影产量:','@count')])

#生成绘图对象
p = figure(plot_width = 700,plot_height = 500,title = '不同导演每年电影均分和产量',
tools = [hover,'box_select,wheel_zoom,reset,crosshair'])
#绘制散点图
p.circle(x= 'year',y='score_mean',source = source,size = 'size',
legend = 'dir',color = factor_cmap('dir',palette=BrBG4, factors=dy_lst))

show(p)

说明:
1.分析导演与烂片的关系,这里有两个标准:第一是导演的影片较多,这里要大于10部,第二有烂片产生。首先要对’导演’字段进行分割连接,然后根据导演分组计数,筛选出大于10部的导演,然后对筛选出来的数据计算烂片数量和烂片咱比,筛选出有烂片的导演数据。
2.然后对这些导演的数据根据不同年份绘制散点图,看该导演在不同年份的导演影片的数量和质量。
3.根据散点可知,导演影片较多且有烂片的导演有三个:周伟,王晶,邓衍成。导演影片多说明三个导演都比较收市场和投资者欢迎,资源交丰富,有烂片说明该导演的水平有起伏。根据散点图可以看出三个导演早期影片评分较高,随时间推移评分降低,时间分割点大概在2010年。

5.结论:

  • 该项目所需的分析指标相对比较简单,但是指标较多,所需要的工作主要集中在数据的清洗和筛选汇总上面,需要对pandas的运用比较娴熟。
  • 对于一个项目如果没有比较清晰的分析点和统计量的话,可以对与分析要点相关各个要素进行分析,通过全面的分析找出有用的分析点和结论。
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: