观影大数据分析(中)

数据分析

why

想要探索影响票房的因素,从电影市场趋势,观众喜好类型,电影导演,发行时间,评分与 关键词等维度着手,给从业者提供合适的建议。

what

电影类型:定义一个集合,获取所有的电影类型

# 获取电影类型

genre_list = set()
for i in df['genres'].str.split(','):
    genre_list = set().union(i, genre_list)

print(genre_list)

注意到集合中存在多余的元素:空的单引号,所以需要去除

# 去除多余元素
genre.discard('')

电影类型数量(绘制条形图)

type_num = genre_df.sum().sort_values(ascending = False)
bar_x = type_num.index
bar_y = type_num

# 设置matplotlib正常显示中文和负号
plt.rcParams['font.sans-serif']=['SimHei']   # 用黑体显示中文
plt.rcParams['axes.unicode_minus']=False     # 正常显示负号

plt.figure(figsize= (15, 8), dpi = 80)
plt.bar(bar_x, bar_y)

# 设置x轴
plt.xlabel('电影类型')
plt.ylabel('数量')
plt.show()

电影类型占比(绘制饼图)

type_proportion = type_num / type_num.sum()

# 可视化
plt.figure(figsize=(15, 8), dpi = 80)

# 设置matplotlib正常显示中文和负号
plt.rcParams['font.sans-serif'] = ['SimHei']   # 用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False     # 正常显示负号

pie_x = type_proportion[type_proportion > 0]
pie_labels = type_proportion[type_proportion > 0].index
explode = (pie_x < 0.05) / 5
plt.pie(pie_x, labels = pie_labels, explode = explode)
plt.title('电影类型占比', fontsize = 20)
plt.show()

电影类型变化趋势(绘制折线图)

# 增加一列。发布年份
genre_df['year'] = df['release_year']

# 将年份作为索引值
genre_df.set_index('year')

# 根据年份分类
genre_year_sum = genre_df.groupby('year').sum()
plt.figure(figsize = (25, 12), dpi = 80)
plt.plot(genre_year_sum)

plt.legend(genre_year_sum.columns, fontsize = 15)

plt.title("电影类型变化趋势", fontsize = 20)
plt.xlabel("年份")
plt.ylabel("电影数量")

plt.show()

不同电影类型预算/利润(绘制组合图)

df['profit'] = df['revenue'] - df['budget']

# 计算不同电影类型的利润

# Step1-创建profit_dataframe
profit_df = pd.DataFrame()

profit_df = pd.concat([genre_df.reset_index(), df['profit']], axis=1)

# Step2-创建profit_series,横坐标为genre
profit_s=pd.Series(index=genre_list)

# Step3-求出每种genre对应的利润均值
for i in genre_list:
    profit_s.loc[i]=profit_df.loc[:,[i,'profit']].groupby(i, as_index=False).mean().loc[1,'profit']
profit_s = profit_s.sort_values(ascending = True)

profit_s

# 计算不同类型电影的budget
# Step1-创建profit_dataframe
budget_df = pd.DataFrame()
budget_df = pd.concat([genre_df.reset_index(), df['budget']], axis=1)

# Step2-创建budget_series,横坐标为genre
budget_s=pd.Series(index=genre_list)

# Step3-求出每种genre对应的预算均值
for j in genre_list:
    budget_s.loc[j]=budget_df.loc[:,[j,'budget']].groupby(j, as_index=False).mean().loc[1,'budget']
budget_s

# 再接着,横向合并 profit_s 和 budget_s
profit_budget = pd.concat([profit_s, budget_s], axis=1)
profit_budget.columns = ['profit', 'budget']

#添加利润率列
profit_budget['rate'] = (profit_budget['profit']/profit_budget['budget'])*100

# 降序排序
profit_budget_sort=profit_budget.sort_values(by='budget',ascending = False)
profit_budget_sort.head(2)

# 绘制不同类型电影平均预算和利润率(组合图)
x = profit_budget_sort.index
y1 = profit_budget_sort.budget
y2 = profit_budget_sort.rate

# 返回profit_budget的行数
length = profit_budget_sort.shape[0]
fig = plt.figure(figsize=(12,9))

# 左轴
ax1 = fig.add_subplot(1,1,1)
plt.bar(range(0,length),y1,color='b',label='平均预算')
plt.xticks(range(0,length),x,rotation=90, fontsize=12)  # 更改横坐标轴名称
ax1.set_xlabel('年份')                   # 设置x轴label ,y轴label
ax1.set_ylabel('平均预算',fontsize=16)
ax1.legend(loc=2,fontsize=12)

#右轴
# 共享x轴,生成次坐标轴
ax2 = ax1.twinx()
ax2.plot(range(0,length),y2,'ro-.') 
ax2.set_ylabel('平均利润率',fontsize=16)
ax2.legend(loc=1,fontsize=12)

# 将利润率坐标轴以百分比格式显示
import matplotlib.ticker as mtick
fmt='%.1f%%'
yticks = mtick.FormatStrFormatter(fmt)
ax2.yaxis.set_major_formatter(yticks)

# 设置图片title
ax1.set_title('不同类型电影平均预算和利润率',fontsize=20)
ax1.grid(False)
ax2.grid(False)
plt.savefig("不同电影平均预算+利润率.png",dpi=300)

plt.show()

# 绘制不同类型电影预算和利润(条形图)
profit_budget_sort.iloc[:,0:2].plot(kind='bar', figsize=(12,9),color = ['blue', 'r'])
plt.title('Budget and Profit',fontsize = 20)
plt.xlabel('len',fontsize = 16)
plt.grid(False)
plt.savefig('不同类型电影预算和利润-条形图.png',dpi=300)

电影关键词

# 引入包
from wordcloud import WordCloud

#keywords关键词分析
keywords_list = []
for i in df['keywords']:
    keywords_list.append(i)

# 将所有nan转换成空字符串
df = df.where(df.notnull(), '')

keywords = ",".join(keywords_list)

wordcloud = WordCloud(
                background_color = 'black',
                stopwords = [],
                random_state=9, # 设置一个随机种子,用于随机着色
                max_words = 3000,
                width = 2400,
                height = 1200,
                scale=1).generate(keywords)

plt.figure(figsize = (23, 8), dpi = 80)
plt.imshow(wordcloud)
plt.axis("off")
plt.show()

when

查看runtime的类型,发现是object类型,也就是字符串,所以,先进行数据转化。

# 转换数据类型
df.runtime = df.runtime.convert_objects(convert_numeric=True)
df.runtime.describe()

电影时长(绘制电影时长直方图)


# 设置matplotlib正常显示中文和负号
plt.rcParams['font.sans-serif'] = ['SimHei']   # 用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False     # 正常显示负号

plt.figure(figsize= (23, 10), dpi = 80)
plt.hist(df.runtime, bins = 40, facecolor="blue", edgecolor="black", alpha=0.7)

# 显示横轴标签
plt.xlabel("电影市场")
# 显示纵轴标签
plt.ylabel("频数/频率")
# 显示图标题
plt.title("频数/频率分布直方图", fontsize = 20)
plt.show()

发行时间(绘制每月电影数量和单片平均票房)

x = list(range(1, 13))
# 影片数量
film_num = df.groupby('release_month').size()
# 每月单片平均票房
revenue_mean = df.groupby('release_month').revenue.mean()

plt.figure(figsize = (23, 12), dpi = 200)
fig,ax1 = plt.subplots()
ax2 = ax1.twinx()           # 做镜像处理
ax1.bar(x, film_num)
ax2.plot(x, revenue_mean, color = 'r')

ax1.set_xlabel('月份', fontsize = 12)    #设置x轴标题
ax1.set_ylabel('每月电影数量',color = 'g', fontsize = 12)   #设置Y1轴标题
ax2.set_ylabel('单片平均利润',color = 'b', fontsize = 12)   #设置Y2轴标题

where

本数据集收集的是美国地区的电影数据,对于电影的制作公司以及制作国家,在本次的故事背景下不作分析。

who

分析票房分布及票房Top10的导演

revenue = df['revenue']

plt.figure(figsize = (26, 15), dpi = 200)
# 刻度字体大小13
plt.tick_params(labelsize = 20)
plt.subplot(221)
plt.hist(revenue, bins = 100, color = 'blue', facecolor="blue", edgecolor="black", alpha=0.7)
plt.title("票房分布", fontsize = 20)
plt.subplot(222)
director_df = df[['crew', 'revenue', 'vote_average']]
director_df = director_df.groupby('crew').mean()
director_revenue_top10 = director_df.sort_values(ascending = True, by = 'revenue').tail(10)

bar_x = director_revenue_top10.index
bar_y = director_revenue_top10.revenue

plt.bar(bar_x, bar_y, color = 'blue')
plt.xticks(rotation = 30)
plt.title("票房Top10导演", fontsize = 20)

plt.show()

分析评分分布及评分Top10导演

vote = df['vote_average']

plt.figure(figsize = (26, 15), dpi = 200)

# 刻度字体大小13
plt.tick_params(labelsize = 20)

plt.subplot(221)
plt.hist(vote, bins = 200, color = '#3c5e91', facecolor="#3c5e91", edgecolor="black", alpha=0.7)
plt.title("评分分布", fontsize = 20)

plt.subplot(222)

director_vote_top10 = director_df.sort_values(ascending = True, by = 'vote_average').tail(10)

bar_x = director_vote_top10.index
bar_y = director_vote_top10.vote_average

plt.bar(bar_x, bar_y, color = '#3c5e91')
plt.xticks(rotation = 30)
plt.title("评分Top10导演", fontsize = 20)

plt.savefig("分析评分分布及评分Top10导演", dpi = 300)

plt.show()

how

原创VS改编(饼图)

# 改编
based = pd.DataFrame()
based['title'] = df[df['keywords'].str.contains('based on')].title
based['budget'] = df[df['keywords'].str.contains('based on')].budget
based['revenue'] = df[df['keywords'].str.contains('based on')].revenue

# 原创
original = pd.DataFrame()
original['title'] = df[df['keywords'].str.contains('based on') == False].title
original['budget'] = df[df['keywords'].str.contains('based on') == False].budget
original['revenue'] = df[df['keywords'].str.contains('based on') == False].revenue

# 可视化

# 数据总数量
total_num = len(df)

# 改编数量
based_num = len(based)

# 原创数量
original_num = len(original)

plt.figure(figsize=(15,7), dpi = 75)
labels= ['改编', '原创']
sizes = [based_num/total_num, original_num/total_num]
explode = (0.1, 0)
plt.pie(sizes,explode=explode,labels=labels,autopct='%1.1f%%',shadow=False,startangle=150)
plt.title("原创VS改编占比", fontsize = 20)
plt.show()  

原创VS改编预算/利润率(组合图)

bar_x = [1, 2]
width = 0.1
labels = ["改编", "原创"]

# 预算
bar_y1 = [based['budget'].sum(), original['budget'].sum()]
# 利润
bar_y2 = [based['revenue'].sum(), original['revenue'].sum()]
plot_y = [(based['revenue'].sum() - based['budget'].sum())/based['budget'].sum(), (original['revenue'].sum() - original['budget'].sum())/original['budget'].sum()]

plt.figure(figsize= (132, 125), dpi = 200)

fig,ax1 = plt.subplots()
ax2 = ax1.twinx() 

ax1.bar([i-width/2 for i in bar_x], bar_y1, width = width, label = "预算")
ax1.bar([i+width/2 for i in bar_x], bar_y2, width = width, label = "票房")
ax1.set_xticks(bar_x)
ax1.set_xticklabels(labels)
ax1.legend()

ax2.plot(bar_x, plot_y, color='red', linestyle='--', marker = 'o')
ax2.legend("平均利润率")

plt.show()

how much

计算相关系数(票房相关系数矩阵)

import seaborn as sns

revenue_corr = df[['runtime','popularity','vote_average','vote_count','budget','revenue']].corr()

plt.figure(figsize = (25, 12), dpi = 20)
plt.rcParams['figure.figsize']=(120,120)
sns.heatmap(
            revenue_corr,
            annot=True, # 在每个单元格内显示标注
            cmap="Blues", # 设置填充颜色:黄色,绿色,蓝色
            cbar=True,  # 显示color bar
            linewidths=0.5, # 在单元格之间加入小间隔,方便数据阅读
           )

plt.savefig('票房相关系数矩阵.png',dpi=300)

票房影响因素散点图

# 绘制散点图
fig = plt.figure(figsize=(17,5))

# 预算影响
budget_revenue = df[['budget', 'revenue']]

ax1 = plt.subplot(1,3,1)
ax1 = sns.regplot(x='budget', y='revenue', data=budget_revenue, x_jitter=.1,color='r',marker='x')
ax1.text(1.6e8,2.2e9,'r=0.7',fontsize=16)
plt.title('预算影响',fontsize=20)
plt.xlabel('预算',fontsize=16)
plt.ylabel('收入',fontsize=16)
 
# 受欢迎度影响
popularity_revenue = df[['popularity', 'revenue']]
ax2 = plt.subplot(1,3,2)
ax2 = sns.regplot(x='popularity', y='revenue', data=popularity_revenue, x_jitter=.1,color='g',marker='o')
ax2.text(500,3e9,'r=0.59',fontsize=16)
plt.title('受欢迎程度影响',fontsize=18)
plt.xlabel('欢迎程度',fontsize=16)
plt.ylabel('收入',fontsize=16)

# 投票数
vote_revenue = df[['vote_count', 'revenue']]
ax3 = plt.subplot(1,3,3)
ax3 = sns.regplot(x = 'vote_count', y = 'revenue', data = vote_revenue, x_jitter = .1,color='b',marker='v')
ax3.text(7000,2e9,'r=0.75',fontsize=16)
plt.title('投票数量影响',fontsize=20)
plt.xlabel('投票数量',fontsize=16)
plt.ylabel('收入',fontsize=16)

plt.show()

原文地址:https://www.cnblogs.com/Gazikel/p/15685294.html