七、电影数据分析

七、电影数据分析

7.1 背景介绍

7.1.1实验背景

电影娱乐产业越发发达,投资商希望能从电影的各种数据中找到最可能赚钱的电影有什么特点。

数据介绍

  • budget 预算
  • genres 电影名数据
  • homepage 网站主页
  • id
  • keywords 关键字
  • original_language 语言
  • original_title 标题
  • overview 概述
  • popularity 人气
  • popularity 电影商
  • production_countries 电影商拍摄地
  • release_date 发布日期
  • revenue 收入
  • runtime 电影时长
  • spoken_languages 电影语言
  • status 状态
  • status 标语
  • title 标题
  • vote_average 评分
  • 评分人数
  • movie_id 电影id
  • title 标题
  • cast 投票人信息
  • crew 所有信息

7.2 载入数据

7.2.1 导入支持库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import json
7.2.3 设置中文标签显示
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
7.2.4 载入数据集
movies=pd.read_csv(r'../data/tmdb_5000_movies.csv',sep=',')
credit=pd.read_csv(r'../data/tmdb_5000_credits.csv',sep=',')

7.3 数据清洗

7.3.1 检查两个id列和title列是否真的相同
(movies['id']==credit['movie_id']).describe()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m8rXBfbQ-1629090102555)(Matplotlib基础课程.assets/Matplotlib_10_1.png)]

(movies['title']==credit['title']).describe()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2qFw2TAL-1629090102557)(Matplotlib基础课程.assets/Matplotlib_10_2.png)]

7.3.2 删除多余列
del credit['movie_id']
del credit['title']
del movies['homepage']
del movies['spoken_languages']
del movies['original_language']
del movies['original_title']
del movies['overview']
del movies['tagline']
del movies['status']
7.3.3 合并两个数据集
full_df=pd.concat([credit,movies],axis=1)#横向连接
7.3.4 处理缺失值-首先找到缺失值
nan_x=full_df['runtime'].isnull()
full_df.loc[nan_x,:]

img

7.3.5 处理缺失值
full_df.loc[2656,'runtime']=98
full_df.loc[4140,'runtime']=82
7.3.6 查找release_data的缺失值
nan_y=full_df['release_date'].isnull()
full_df.loc[nan_y,:]

img

7.3.7 处理release_data的缺失值
full_df.loc[4553,'release_date']='2014-06-01'
7.3.8 将release_date的类型转换成日期类型
full_df['release_date']=pd.to_datetime(full_df['release_date'],errors='coerce',format='%Y-%m-%d')
full_df.info()

img

7.3.9 转换成日期格式后,提取对应的年份
full_df['release_year']=full_df['release_date'].map(lambda x : x.year)
full_df.loc[:,'release_year'].head()

img

7.3.10 处理json格式类型-提取json格式,使用json.loads将json格式转化成字符串
json_cols=['genres','keywords','production_companies','production_countries','cast','crew']
for i in json_cols:
    full_df[i]=full_df[i].apply(json.loads)
    
def get_names(x):
    return ','.join(i['name'] for i in x)

full_df['genres']=full_df['genres'].apply(get_names)
full_df['keywords']=full_df['keywords'].apply(get_names)
full_df['production_companies']=full_df['production_companies'].apply(get_names)
full_df['production_countries']=full_df['production_countries'].apply(get_names)
full_df['genres'].head()

img

7.3.11 获取所有电影类型
real_genres=set()
for i in full_df['genres'].str.split(','):
    real_genres=real_genres.union(i)
real_genres=list(real_genres)#将集合转换成列表
real_genres.remove('')#删除空格
print(real_genres)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bv5LlMku-1629090102565)(Matplotlib基础课程.assets/Matplotlib_10_8.png)]

7.3.12 将所有类型添加到列表
for i in real_genres:
  full_df[i]=full_df['genres'].str.contains(i).apply(lambda x:1 if x else 0)
full_df.head(2)

img

7.3.13 获取年份和类型子集,按年分组统计每年各类型电影数量
part1_df=full_df[['release_year', 'Family', 'War', 'Documentary', 'Mystery', 'Foreign','Science Fiction', 'History', 'Adventure', 'Music', 'Animation',
       'Western', 'Action', 'Crime', 'Comedy', 'Drama', 'Romance', 'Horror','Thriller', 'Fantasy', 'TV Movie']]

year_cnt=part1_df.groupby('release_year').sum()
year_cnt.tail()

img

7.3.14 每年电影类别数量
plt.figure(figsize=(10,6))
plt.rc('font',family='SimHei',size=10)#设置字体和大小,否则中文无法显示
ax1=plt.subplot(1,1,1)
year_cnt.plot(kind='line',ax=ax1)
plt.title('每年电影类型数量')

img

7.3.15 不同电影类型总数量
genre=year_cnt.sum(axis=0)#对列求和
genre=genre.sort_values(ascending=True)
genre

img

7.4 简单绘图分析

7.4.1 绘制分类数据横向条形图
plt.figure(figsize=(10,6))
plt.rc('font',family='STXihei',size=10.5)
ax2=plt.subplot(1,1,1)
label=list(genre.index)
data=genre.values
rect=ax2.barh(range(len(label)),data,color='#03A2FF',alpha=1)
ax2.set_title('不同电影类型数量')#设置标题
ax2.set_yticks(range(len(label)))
ax2.set_yticklabels(label)
#添加数据标签
for x,y in zip(data,range(len(label))):
    ax2.text(x,y,'{}'.format(x),ha='left',va='center')

img

7.4.2 计算不同类型电影收入(亿元)
r={}
for i in real_genres:
    r[i]=full_df.loc[full_df[i]==1,'revenue'].sum(axis=0)/100000000
revenue=pd.Series(r).sort_values(ascending=True)
revenue

img

7.4.3 绘制电影收入的横向条形图
plt.figure(figsize=(12,6))
plt.rc('font',family='Simhei',size=10.5)
ax=plt.subplot(1,1,1)
label=revenue.index
data=revenue.values
ax.barh(range(len(label)),data,color='#03A2FF',alpha=1)
ax.set_yticks(range(len(label)))#设置y轴刻度
ax.set_yticklabels(label)#设置刻度名称
ax.set_title('不同类型电影收入')
#添加数据标签
for x,y in zip(data,range(len(label))):
    ax.text(x,y,'{:.1f}'.format(x))#坐标位置,及要显示的文字内容

img

7.4.4 票房收入影响因素分析
corr=full_df.corr()#计算各变量间的相关系数矩阵
corr_revenue=corr['revenue'].sort_values(ascending=False)#提取收入与其他变量间的相关系数,并从大到小排序
corr_revenue.head(10)

img

7.4.5 绘制散点图,分析budget与revenue的相关性
x=full_df.loc[:,'budget']
y=full_df.loc[:,'revenue']
plt.rc('font',family='SimHei',size=10.5)
plt.scatter(x,y,color='#03A2FF')
plt.xlabel('budget')
plt.ylabel('revenue')
plt.title('budget与revenue的散点图')
plt.show()

img

7.4.6 原创电影与改编电影分析
part2_df=full_df.loc[:,['release_year','keywords']]
part2_df['based_on_novel']=part2_df['keywords'].str.contains('based on novel').apply(lambda x:1 if x else 0)  
part2_df['not_based_on_novel']=part2_df['keywords'].str.contains('based on novel').apply(lambda x:0 if x else 1)  
part2_df.head()

img

novel_per_year=part2_df.groupby('release_year')['based_on_novel','not_based_on_novel'].sum()
novel_per_year.tail()

img

7.4.7 绘制原创电影与改变电影趋势图
novel_per_year.plot()
plt.rc('font',family='SimHei',size=10.5)
plt.title('原创电影与改编电影数量趋势图')

img

7.4.8 原创电影与改编电影总数
novel_all=[part2_df['based_on_novel'].sum(axis=0),part2_df['not_based_on_novel'].sum(axis=0)]
novel_rate=novel_all/sum(novel_all)
novel_rate

img

7.4.9 绘制原创电影和改编电影比例饼图
plt.figure(figsize=(6,6))
plt.rc('font',family='SimHei',size=10.5)
ax=plt.subplot(111)#与plt.sumplot(1,1,1)效果一样
labels=['based_on_novel','not_based_on_novel']
colors=['#03A2FF','#0AAA99']
ax.pie(novel_rate,labels=labels,colors=colors,startangle=90,autopct='%1.1f%%')
ax.set_title('原创电影与改编电影数量占比')

img

7.5 复杂绘图分析

分析电影主题关进词

7.5.1 获取所有关键词及其对应词频
keywords_dic={}
def get_keywords(x):
    for i in x:
        keywords_dic[i]=keywords_dic.get(i,0)+1
    return keywords_dic[i]     

keywords = full_df['keywords'].str.split(',').apply(get_keywords)
keywords

img

7.5.2 绘制词云图

安装wordcloud安装包:!pip install wordcloud

import matplotlib.pyplot as plt
from wordcloud import WordCloud,STOPWORDS
import pandas as pd

wordcloud=WordCloud(max_words=500 #最大词数
#                    ,font_path="DejaVuSerif.ttf" 
#自定义字体
                    ,background_color="white" #背景颜色
                    ,max_font_size=80 #最大字号
                    ,prefer_horizontal=100 #词语水平方向排版出现的频率,设置为100表示全部水平显示
                    ,stopwords=STOPWORDS #使用屏蔽词
                    )
wordcloud=wordcloud.fit_words(keywords_dic)
plt.imshow(wordcloud)
plt.axis('off')
plt.show()
wordcloud.to_file('worldcloudt.jpg')

img

7.5.3 统计各个国家的电影数
part3_df=full_df[['production_countries','id','release_year']]#提取需要的列子集
#由于有的电影产地属于多个国家,故需要对production_countries进行分列
split_df=pd.DataFrame([x.split(',') for x in part3_df['production_countries']],index=part3_df.index)
#将分列后的数据集与源数据集合并
part3_df=pd.merge(part3_df,split_df,left_index=True,right_index=True)
#下面代码实现列转行
st_df=part3_df[['release_year',0,1,2,3]]
st_df=st_df.set_index('release_year')
st_df=st_df.stack()
st_df=st_df.reset_index()

st_df=st_df.rename(columns={0:'production_countries'})#对列重命名
countries=st_df['production_countries'].value_counts()#统计各个国家的电影数
countries.sum()
countries_rate=countries/countries.sum()#计算占比
countries_top5=countries_rate.head(5)
other={'other':1-countries_top5.sum()}
countries_top6=countries_top5.append(pd.Series(other))
countries_top6

img

7.5.4 绘制安国家分类的电音出品饼图
labels=list(countries_top6.index)
plt.figure(figsize=(6,6))
plt.rc('font',family='SimHei',size=10.5)
ax=plt.subplot(1,1,1)
ax.pie(countries_top6,labels=labels,startangle=90,autopct='%1.1f%%')
ax.set_title('电影产地分布')

img

7.5.5 统计各个电影公司电影数
part4_df=full_df[['production_companies','release_year']]
split_df=pd.DataFrame([x.split(',') for x in part4_df['production_companies']],index=part4_df.index)
part4_df=pd.merge(part4_df,split_df,left_index=True,right_index=True)
del part4_df['production_companies']
part4_df=part4_df.set_index('release_year')
part4_df=part4_df.stack()
part4_df=part4_df.reset_index()
part4_df=part4_df.rename(columns={0:'production_companies'})
companies=part4_df['production_companies'].value_counts()
companies_top10=companies[companies.index!=''].head(10)
companies_top10

img

7.5.6 绘制电影公司条形图
plt.figure(figsize=(10,6))
plt.rc('font',family='SimHei',size=10.5)
ax=plt.subplot(111)
ax.barh(range(10),companies_top10.values,color='#03A2FF')
ax.set_title('电影公司top10')
ax.set_yticks(range(10))
ax.set_yticklabels(companies_top10.index)
for x,y in zip(companies_top10.values,range(10)):
    ax.text(x,y,'{}'.format(x),ha='left',va='center')

img

一、数据分析项目介绍 1. 项目所需的模块库介绍 pandas用法: 需要导入以下模块 import numpy as np import pandas as pd from pandas import Series, Dataframe 2.项目背景介绍 互联网电影资料库(Internet Movie Database,简称IMDB)是一个关于电影演员、电影、电视节目、电视明星和电影制作的在线数据库。电影作为艺术和娱乐载体已成为我们生活中的一部分,作为电影爱好者之一,希望通过分析了解电影市场大体情况,以便于以后选择电影观看。 使用的数据是IMDB美国票房排名前1000的电影数据,数据包含了电影名称,票房金额,上映年份,演职人员,IMDB评分,电影类型等信息,数据中的很多电影大家也比较熟悉。相信不少人都有这样的经历,当想要看一部电影的时候,会去百度一下谁是导演,谁是主演。如果导演是克里斯托弗•诺兰,心里已经给电影打了个8分以上的评分了。而阿汤哥的动作片,预期也都能肾上腺素飙升。对于已上映的电影,不少人会去豆瓣搜索现时的评分,或是前作的评价,若是豆瓣高分、高评论数,也会按奈不住去蹭下热度。如果要去电影院观看的话,想必不少人会更倾向选择动作片或者科幻大片这类特效丰富,影音冲击强烈的电影。近几年特效技术和3D动画的日渐成熟,影院观影已经是越来越多人的第一选择。 IMDB的资料中包括了影片的众多信息、演员、片长、内容介绍、分级、评论等。对于电影的评分目前使用最多的就是IMDB评分。 截至2018年6月21日,IMDB共收录了4,734,693部作品资料以及8,702,001名人物资料。 3.项目所需数据介绍 数据的属性包括:电影名称、评论数、评分、导演、上映时间、上映国家、主要演员、语言、IMDB评分等。 理解数据: color 、director_name 、num_critic_for_reviews、duration、director_facebook_likes 、actor_3_facebook_likes、actor_2_name 、actor_1_facebook_likes 、gross 、genres 、actor_1_name 、movie_title 、num_voted_users、cast_total_facebook_likes 、actor_3_name 、facenumber_in_poster 、plot_keywords 、movie_imdb_link 、num_user_for_reviews、language 、country、content_rating、budget、title_year 、actor_2_facebook_likes 、imdb_score 、aspect_ratio 、movie_facebook_likes 4.项目功能详细介绍 显示电影评分分布的情况; 电影数量与平均分年度变化的情况; 评论家评论数与评分的关系; 评分与电影票房的关系; 电影数量大于5前提下平均分前十的导演推荐的数据; 不同电影类型的年份累计分析; 电影时长的分布及时长是否和评分有相关性; 电影时长的分布及时长是否和评分有相关性。 二、数据分析过程 1.主要功能实现的类和方法介绍 # 清洗runtime电影时长列数据,可使用str.split()方法 df['runtime'] = df['runtime'].str.split('').str.get(0).astype(int) df['runtime'].head() # 清洗year列,使用str[:]选取年份数字并转换成int类型,使用df.unique()方法检查数据 df['year'] = df['year'].str[-5:-1].astype(int) df['year'].unique() 2. 数据分析过程代码和解释说明 导入包: 导入、查看、清洗数据: 评分分布图: 电影数量与平均分布年度变化: 评论家评论数&评分、评分&票房: 电影数量大于5平均分前十的导演: 统计不同年份、不同类型电影的数量: cumsum = df.groupby(['main_genre', 'year']).title.count() # 使用累加功能统计1980年起不同年份不同电影类型的累计数量,对于中间出现的缺失值,使用前值填充 genre_cumsum = cumsum.unstack(level=0).cumsum().ffill() # 只选取总数量大于50的电影类型数据 genre_cumsum = genre_cumsum.loc[:,genre_cumsum.iloc[-1,:] >= 50] # 根据电影类型统计数据作图 fig, ax2 = plt.subplots(figsize=(12,6)) genre_cumsum.plot(ax=ax12, legend=False, linewidth=3) # 添加数据标签 for i in last_row.iteritems(): if i[0] == 'Adventure' or i[0] == 'Biography' or i[0] == 'Horror': ax2.annotate('{} {}'.format(int(i[1]), i[0]), xy=(2018.5, i[1]-5), fontsize=12) else: ax2.annotate('{} {}'.format(int(i[1]), i[0]), xy=(2018.5, i[1]+5), fontsize=12) # 美化图表 ax2.set_title('The Aggregate Movies of Different Genres Over Years', fontsize=16) ax2.spines['top'].set_visible(False) ax2.spines['right'].set_visible(False) ax2.spines['left'].set_visible(False) ax2.tick_params(bottom=True, labelleft=False) ax2.set_xlabel('') plt.tight_layout() 电影时长的分布及时长是否和评分有相关性: fig, ax4 = plt.subplots() df['runtime_min'].hist(range=(70,210), bins=14, color=(114/255,158/255,206/255)) ax4.set_title('The Runtime Distribution of US Top Box Office Movies') ax4.spines['top'].set_visible(False) ax4.spines['left'].set_visible(False) ax4.spines['right'].set_visible(False) ax4.set_xticklabels(np.arange(70,220,10)) ax4.set_xticks(np.arange(70,220,10)) ax4.grid() 绘制时长和IMDB评分相关性: fig = plt.figure(figsize=(14,7)) sns.lmplot(data=df, x='runtime_min', y='imdb_rate') sns.despine() 三、数据分析结果评估 1、评分分布主要在5.0~8.0之间,3.0以下和9.0以上分布很少。如果8.0算为优秀,则优秀电影占比较少。 2、电影数量在1990~2000年间快速增长,2009年达到较高值。而电影的平均分整体上呈下降趋势。 3、评论家评论数与评分整体呈正相关关系,500以上评论家评论数对应的评分都高于6.0。 4、评分与票房整体呈正相关关系,但关系不强。 IMDB评分人数和电影票房的相关性很弱,高票房不代表评分人数多,低票房电影也能有大量的IMDB评分人数。 5、电影数量大于5平均分前十的导演:Christopher Nolan、Quentin Tarantino 、 Stanley Kubrick、 James Cameron 、Peter Jackson 、Alejandro G. Iñárritu 、David Fincher 、Martin Scorsese 、 Wes Anderson 、Paul Greengrass。 6. 前五大电影类型分别是动作片Action,喜剧片Comedy,动画片Animation,剧情片Drama,冒险片Adventure。1995年之前,动作片和喜剧片都是影院观众最喜爱的电影类型,对应的高票房数量不分伯仲,剧情片是另一相对流行的电影类型。1995年后,高票房的动作片快速增长,甩开了喜剧片。喜剧片随仍是高票房数量第二多的电影类型,但近几年增速明显放缓。高票房动画片进入榜单的时间最晚,但在1998年前后迎来明显增长,此后的十年里完成了对剧情片和冒险片的超越。如果动画片保持目前的增速,有望在之后的十几二十年里超越喜剧片,成为高票房数量第二的电影类型。 7. 时长和IMDB评分呈一定的相关性,时长短的电影既有高分也有低分,但时长超过160分钟的电影基本都能获得6分以上的分数,时长最长的两部电影甚至得到了接近9分的超高得分,IMDB评分接近或低于4分的电影时长均小于130分钟。丰富的剧情和长长的故事也许也是一种容易感染观众的方式,这也和之前提到的好的故事打动观众相呼应。 四、总结 数据分析的过程往往是一个从宏观到微观的过程。先从宏观上把握数据大体的情况,大胆地提出假设,然后再将数据进行细分,小心地求证。通过数据的对比,就很容易看出调整的效果。 有关活动效果的数据分析往往也会涉及数据的对比。具体的思路是从要分析的目的入手,首先思考造成这种情况的可能原因有什么,再从每个可能的原因中找到相应的数据,与要分析的目的的数据进行比较,看哪一个是造成该情况发生的主要原因。 这里要用到的是excel的图表工具,把每一种可能的数据都作出一个图表,与要分析的目的的数据图表进行比较,如果有某一个数据的变化曲线与之相差不多,则可以说这个所对应的原因是造成该情况发生的主要原因。 以上是分析活动的一些核心数据,核心数据的分析是最主要的,因为这直接反应了该活动最本质的效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小石小石摩西摩西

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值