观影大数据分析(中)
数据分析
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()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南