简介: 本数据集中包含 1 万条电影信息,信息来源为“kaggle电影数据库”(TMDb,The Movie Database),包括用户评分和票房。 主要为美国地区(1960-2015)的电影作品。
一. 提出问题
本次数据分析的核心任务是:
- 通过对历史电影数据的统计分析,运用集中趋势测量,离散程度测量等等,对数据进行描述性统计,为电影公司投资和拍片思路提供一些方向还有角度。
细化为下述几个小问题: - 问题1:什么对于票房的影响最大
- 问题2:电影的投入对于电影票房的影响
- 问题3:不同类型电影的发行量
- 问题4:不同类型电影的收益能力
- 问题5:不同风格电影的受欢迎程度
二、理解数据
工具:Jupyter Notebook
下载好的csv文件:tmdb-movies.csv
导入文件后通过对数据的查看,我们筛选出与问题重点有关的变量:
序号 | 变量名 | 说明 |
---|---|---|
1 | id | tmdb身份标识 |
2 | popularity | 电影受欢迎程度 |
3 | budget | 电影预算(单位:$) |
4 | revenue | 电影收入(单位:$) |
5 | genres | 电影风格 |
6 | release_date | 发行日期 |
7 | vote_count | 评价的次数 |
8 | vote_average | 平均评分 |
9 | release_year | 发行年份 |
三、数据整理
- 对数据集大概的情况进行了解
- 查看是否有数据类型需要转换
- 有无缺失值,是否需要填充或者删除
- 有无冗余数据,是否需要删除
- 查看列标签,与问题无关的列标签可以删除
# 导入语句
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
# 读取文件
df_movie = pd.read_csv('tmdb-movies.csv')
# 查看文件
df_movie.head(1)
# 数据集的行数列数
df_movie.shape
# 数据集的数据类型
df_movie.dtypes
# 检查有无缺失值
df_movie.isnull().sum()
# 检查有无冗余数据
df_movie.duplicated().sum()
# 打印列标签,方便删除用不到的列
for i,v in enumerate(df_movie.columns):
print(i,v)
四、数据清理
- 清理 ['imdb_id', 'original_title', 'cast', 'homepage', 'tagline', 'keywords', 'overview', 'runtime', 'production_companies'] ,以上列标签与问题关联不大。
- 使用id列标签来查看冗余数据是否需要删除,因为id是唯一的,假如有两个一样的id,那么就可以删除多余的数据。
- 检查缺失值所在的列,通过列标签来判断缺失值需要填充还是删除。
# 清理列标签
df_movie.drop(['imdb_id', 'original_title', 'cast', 'homepage', 'tagline', 'keywords', 'overview', 'runtime', 'production_companies'],
axis=1, inplace=True)
# 查看电影数据集的列标签,确定成功
df_movie.head(1)
for i,v in enumerate(df_movie.columns):
print(v)
# 查看冗余数据
df_movie['id'].duplicated().any()
# 删除冗余数据
df_movie.drop_duplicates(inplace=True)
# 检查是否删除成功
df_movie.duplicated().any()
# 检查缺失值所在的列数
df_movie.isnull().any()
# 可以看出缺失值在导演和电影类型当中,可以删除缺失值
df_movie.dropna(inplace=True)
# 检查缺失值是否清理完毕
df_movie.isnull().any()
五、可视化数据
1、什么对于票房的影响最大?
# 计算相关系数矩阵
df_revenue_corr = df_movie.corr()
df_revenue_corr['revenue'].sort_values(ascending=False)
# 根据矩阵从中选出相关性最高的
df_movie[['popularity', 'vote_count', 'budget', 'profit', revenue']].corr()
popularity | vote_count | budget | profit | revenue | |
---|---|---|---|---|---|
popularity | 1.000000 | 0.794798 | 0.541389 | 0.632243 | 0.665637 |
vote_count | 0.794798 | 1.000000 | 0.641547 | 0.761011 | 0.798562 |
budget | 0.541389 | 0.641547 | 1.000000 | 0.564219 | 0.729293 |
profit | 0.632243 | 0.761011 | 0.564219 | 1.000000 | 0.976375 |
revenue | 0.665637 | 0.798562 | 0.729293 | 0.976375 | 1.000000 |
得出:
- 受欢迎程度和票房相关性:0.6656
- 评价次数和票房相关性:0.7986
- 电影预算和票房相关性:0.7293
- 收益和票房相关性:0.9764
以上我们可以看到,相关性最高的是vote_count(投票总数)
,budget(电影投入)
,profit(电影收益)
,popularity(受欢迎程度)
- 由于
vote_count
和profit
都是在票房出来之后才会有,因此相关性最高,但同时也需要剔除。 - 因此对
popularity
和budget
进行可视化。
# 创建票房收入数据框
revenue = df_movie[['popularity', 'budget', 'revenue']]
# 可视化票房收入与受欢迎程度(蓝)的相关性散点图,\并配线性回归线。
fig = plt.figure(figsize=(17, 5))
ax1 = plt.subplot(131)
ax1 = sns.regplot(x='popularity', y='revenue', data=revenue, x_jitter=.1)
plt.title('revenue by popularity',fontsize=15)
plt.xlabel('popularity',fontsize=12)
plt.ylabel('revenue',fontsize=12)
# 可视化票房收入电影预算(红)的相关性散点图,并配线性回归线。
ax2 = plt.subplot(132)
ax2 = sns.regplot(x='budget', y='revenue', data=revenue, x_jitter=.1,color='r',marker='+')
plt.title('revenue by budget',fontsize=15)
plt.xlabel('budget',fontsize=12)
plt.ylabel('revenue',fontsize=12)
绘制线性相关图:
2、电影的投入对于电影票房的影响
# 得出平均预算
budget_mean = df_movie.budget.mean()
# 通过平均预算分出高低预算两组
low_budget = df_movie.query('budget < {}'.format(budget_mean))
high_budget = df_movie.query('budget >= {}'.format(budget_mean))
new_samples = df_movie.shape[0]
new_samples == low_budget['revenue'].count() + high_budget['revenue'].count()
# 得出平均收入
mean_revenue_low = low_vote['revenue'].mean()
mean_revenue_high = high_vote['revenue'].mean()
# 可视化数据
locations = [1, 2]
heights = [mean_revenue_low, mean_revenue_high]
labels = ['Low Budget', 'High Bubget']
plt.bar(locations, heights, tick_label = labels)
plt.title('Average Revenue by Bubget')
plt.xlabel('Budget Content')
plt.ylabel('Revenue')
绘制条形图:
可以看出预算更高的电影,票房也会比低预算的电影更高。
3、不同类型电影的发行量
# 单独提取出genre
set_genre = set()
for x in df_movie['genres']:
set_genre.update(x.split('|'))
set_genre.discard('')
# 转换成dataframe类型
df_genre = pd.DataFrame()
for genre in set_genre:
df_genre[genre] = df_movie['genres'].str.contains(genre).map(lambda x:1 if x else 0)
df_genre['year']=df_movie['release_year']
# 形成新的列
genre_by_year = df_genre.groupby('year').sum()
genresum_by_year = genre_by_year.sum().sort_values()
fig = plt.figure(figsize=(12,10))
ax = plt.subplot(111)
ax = genresum_by_year.plot.bar(alpha=.7)
plt.xticks(rotation=60)
plt.title('Top genre', fontsize=15)
plt.xlabel('genre', fontsize=15)
plt.ylabel('count', fontsize=15)
绘制柱形图:
最受欢迎的前五名:
- Drama(戏剧)
- Comedy(喜剧)
- Thriller(惊险)
- Action(动作)
- Adventure(冒险)
4、不同类型电影的收益能力
# 可可视化数据
fig = plt.figure(figsize=(18,13))
ax1 = fig.add_subplot(111)
plt.bar(x, profit_rate['profit'], label='profit', alpha=.7)
plt.xticks(x,xl,rotation=60,fontsize=12)
plt.yticks(fontsize=12)
ax1.set_title('Profit by genres', fontsize=20)
ax1.set_ylabel('Film Profit',fontsize=18)
ax1.set_xlabel('Genre',fontsize=18)
ax1.set_ylim(0,1.2e11)
ax1.legend(loc=2,fontsize=15)
#次纵坐标轴标签设置为百分比显示
import matplotlib.ticker as mtick
# 添加多一个兄弟轴,另一条y轴
ax2 = ax1.twinx()
ax2.plot(x, profit_rate['profit_rate'], 'ro-', lw=2, label='profit_rate')
# #次纵坐标轴标签设置为百分比显示
fmt='%.2f%%'
yticks = mtick.FormatStrFormatter(fmt)
ax2.yaxis.set_major_formatter(yticks)
plt.yticks(fontsize=15)
ax2.set_ylabel('Profit_rate',fontsize=18)
ax2.legend(loc=1,fontsize=15)
plt.grid(0)
绘制条形图和折线图:
收益能力最高的五个类型:
- Adventure(冒险)
- Action(动作)
- Comedy(喜剧)
- Drama(喜剧)
- hriller(惊险)
5、不同类型电影的受欢迎程度
# 创建受欢迎程度的数据框
df_popularity = pd.DataFrame()
df_popularity = pd.concat([df_genre.iloc[:, :-1], df_movie['popularity']], axis=1)
df_popularity.head()
# 计算每个风格电影的受欢迎程度的均值
popularity_mean = []
for genre in set_genre:
popularity_mean.append(df_popularity.groupby(genre, as_index=False).mean().loc[1,'popularity'])
genre_popularity = pd.DataFrame(index=set_genre)
genre_popularity['popularity_mean'] = popularity_mean
genre_popularity.sort_values('popularity_mean', inplace=True)
# 可视化数据
fig = plt.figure(figsize=(14, 8))
ax = plt.subplot(111)
genre_popularity.plot(ax=ax, kind='barh')
plt.title('Popularity by genre', fontsize=18)
plt.xlabel('Mean of popularity', fontsize=15)
plt.ylabel('Film genres', fontsize=14)
plt.xticks(fontsize=11)
plt.yticks(fontsize=11)
plt.legend(fontsize=11)
绘制横向条形图:
受欢迎程度最高的五个类型:
- Adventure(冒险)
- Science Fiction(科幻小说)
- Fantasy(幻想)
- Action(动作)
- Animation(动画)
六、结论
1.电影类型方面
从收益来看:
- Adventure(冒险)
- Action(动作)
- Comedy(喜剧)
- Drama(戏剧)
- hriller(惊险)
从受欢迎程度来看:
- Adventure(冒险)
- Science Fiction(科幻小说)
- Fantasy(幻想)
- Action(动作)
- Animation(动画)
建议:
- 结合两组数据,我们可以看出
冒险类
,动作类
,喜剧类
,科幻类
的电影收益和受欢迎程度都比较高,建议首选以上四种类型电影。
2.电影投入方面
- 电影投入得越多,正常来说会是个大片,票房也应该会大卖。但还需要其他综合因素的考量,例如演员阵容,导演,电影类型等等。但不可否认的是,电影投入得多,演员阵容也会更豪华,导演知名度较高,才是高票房的保障。因此,如果不考虑其他综合因素情况下,高投入会比低投入电影的票房高。
- 电影投入包含许多的方面,有一个方面也是非常重要,那就是在上映之前,电影的知名度,也就是受欢迎的程度。因此,电影的预算建议多投入在广告宣传方面,在上映之前打响知名度。
提示:
-
本项目分析使用的数据对于探索的问题已经足够
数据量使用足够大,来源于著名的tmdb电影网站,数据量达上万条,足够对探索问题作出相关性的判断。
筛选出的特征足够用于探索目标的分析,电影的票房、预算、收益、受欢迎程度和电影类型。以上筛选出来的数据集大多数与这五个特征有关
-
探索过程中对数据的清洗、处理、操作不会对最后分析带来偏差和不确定性
- 对于缺失值的处理:因为出现缺失值的列数对于最后分析的问题来说,并不在对比之列,因此可以删除
- 对于冗余数据的处理:此数据集只出现了一个冗余数据,并且同一个id,因此可以删除。
- 对于数据类型的处理:数据类型都比较合理,并没有需要转换的数据类型。