2022年全国大学生数据统计与分析竞赛
B题 电影评分的大数据分析
原题再现:
大数据无处不在,在运营一个成功的商业的过程中,大数据起到的非常重要的作用。同样通过观众对电影的评分的分析,可以在一定程度上给电影行业启发。
网络影评是伴随着电子媒介和数字技术诞生的,呈现出鲜明的数据化倾向,比如电影评分、打星、榜单等。网络评分因其便捷、高效,成为大部分观众评价电影的首选方式,也是电影口碑最直观的体现,评分高低直接影响到大众的观影取向和消费选择。与文字、视频相比,大数据搜集、统计的评分信息可以让我们对观众的观影体验,审美趣味、情感态度一目了然。视频网站、电影门户网站等的后台会根据观众的评分、打星和消费行为来推断用户的审美趣味和消费需求,从而为客户提供个性化推荐和引导。
电影的评分更多反映的是大众审美,并非绝对的评判标准,不应该奉为最终裁决,主要功能是用来参考,规避较差电影的同时,发现好的电影,尤其是在规避较差电影方面有着非常显著的效果。
附件1.电影评分.csv中包括了豆瓣影评排名前250名电影的名称、导演、电影类型、国家、上映年份、评分和评论人数。附件2.电影票房.csv中包括了10605 部电影的票房排名、电影名称、上映时间、总票房(元)、平均票价和平均场次,其中,部分数据有缺失和异常。
请你们团队使用附件中的相关数据,进行数据统计与分析,回答下列问题:
问题一:请分析附件1中最受欢迎的电影类型是什么?排名前250名电影中出现次数最多的导演前10名是谁?出现次数最多的国家前5名是哪些国家?
问题二:请分析附件1中排名前250名电影的上映年份主要集中在哪几年?排名前250名电影的评分与评论人数、国家、导演和电影类型是否有关系?
问题三:请你们收集相关数据,分析附件2中电影票房较高的电影主要是什么类型的电影?并给出这些电影的上映时间、总票房(元)、平均票价和平均场次的相关统计图表。
问题四:某导演拟定于2024年春节档推出一部电影,请从数据分析的角度给导演一个提案,例如考虑:电影的类型、题材、上映时间、票价等方面。
整体求解过程概述(摘要)
21 世纪以来,随着互联网的普及,全球进入了信息化时代。从事数据分析工作的研究者可以通过特定技术手段获取互联网平台上产生的大量数据,并采用适当的方法分析这些数据,提取出重要信息并为一些行业的发展提供指导。电影评分数据分析随着互联网、移动设备的普及和线上票务销售等因素的密切相关而越来越流行。通过电影评分的数据分析,可以揭示市场消费者喜好和心理需求,探索不同受众群体的偏好和需求。同时,电影评分数据还可以帮助观众更快速、更准确地找到自己喜欢的电影,提高观影的满意度和质量,同时对电影产业的发展也具有积极的推动作用。但是需要注意,电影评分并非绝对评分标准,应将其作为参考并结合其他因素进行综合评估。
针对问题一:对于第1小问,对附件1中的“电影类型”数据列进行预处理,即按“/”进行划分,统计各个电影类型的出现次数,最后选择频次最高的电影类型剧情为最受欢迎的电影类型。针对问题一的第2小问,对附件1中的“导演”数据列进行处理,统计各个导演名字的频次,选取出现次数最多的前10名导演为:宫崎骏、克里斯托弗.诺兰、史蒂文.斯皮尔伯格、王家卫、李安、大卫.芬奇、今敏、是枝裕和、彼特.道格特、大卫.叶茨。针对问题一的第3小问,对附件1中的“国家”数据列进行处理,统计各个国家的出现次数,最后得出出现次数最多的前5个国家分别为:美国、英国、日本、中国香港和中国大陆。
针对问题二:对于第1小问,对附件1中的“上映年份”数据列进行处理,统计每个上映年份出现的频次,主要分布在20世纪80年代以后的年份,其中21世纪00年代和10年代最为显著,2010 年上映的电影最多,高达14部。针对问题二的第2小问,首先将非数值型数据进行一个数值型数据的转换,用One-hot编码进行处理,然后分别对国家、导演、电影类型和评论人数与电影评分的相关性进行判断,结果表明,电影评分与国家、导演、电影类型和评论人数均相关。最后利用互信息比较电影特征与电影评分之间的相关性,电影评分与国家、导演、电影类型和评论人数的相关性数值分别为2.3672、0.1924、1.8471和0.2502。
针对问题三:对于第1小问,首先进行数据预处理,删除空白数据行以保证数据完整性和准确性。其次设置阈值,将票房高于10亿的电影定义为总票房较高的电影。然后进行相关电影类型的收集,最后统计电影类型的频次,得出票房较高的电影主要是喜剧、动作、冒险类型。针对问题三的第2小问,基于第1小问统计出的票房较高的电影数据集,对其上映时间、总票房(元)、平均票价和平均场次进行频次统计,并绘制相关的统计图表。
针对问题四:旨在分析前三个问题中探讨的影响电影评分的主要因素,并深入研究历年春节档高票房电影的类型特征。同时,在此基础上,提供一个结合电影的类型(喜剧、冒险)、题材(轻松、欢乐)、上映时间(1月31日左右)、票价(36元)等方面的电影推荐方案。
问题重述:
题目的附件 1.电影评分.csv中提供了豆瓣影评排名前 250 名电影的名称、导演、 电影类型、国家、上映年份、评分和评论人数。题目的附件 2.电影票房.csv中提供了10605部电影的票房排名、电影名称、上映时间、总票房(元)、平均票价和平均场次。题目要求我们根据所给的豆瓣影评排名前250名电影数据、10605 部电影的票房数据,通过数学统计和建模方法解决以下问题:
问题一:基于附件 1.电影评分.csv中给出的数据信息进行相关问题的求解。寻找出豆瓣影评排名前 250 名电影中最受欢迎的电影类型是什么,也就是电影类型次数出现最多的是哪种电影类型,以及求解出现次数最多的前10名导演和出现次数最多的前5名国家。
问题二:依旧基于附件 1.电影评分.csv中给出的数据信息进行相关问题的求解,分析出排名前250名的电影哪几年上映的电影最多,以及求解出排名前 250名电影的评分与评论人数、国家、导演和电影类型这些特征变量之间的相关性。
问题三:基于团队收集的相关数据分析出影响电影票房的主要因素有哪些,然后对附件 2.电影票房.csv中提供的数据进行问题求解。得出附件2中10605部电影票房较高的电影主要是什么类型的电影。与此同时给出这些电影的上映时间、总票房(元)、平均票价和平均场次的相关统计图表。
问题四:问题四考虑前三问求解出的影响电影评分的主要因素,以及往期春节期间上映的高票房的电影主要是什么类型的,最后给出一个结合电影的类型、题材、上映时间、票价等方面的电影提案。
模型的建立与求解整体论文缩略图
全部论文请见下方“ 只会建模 QQ名片” 点击QQ名片即可
部分程序代码:(代码和文档not free)
import pandas as pd
import numpy as np
data = pd.read_csv("附件1. 电影评分.csv",header=0, encoding="gbk")
data['电影类型'].value_counts()
biaoqian = pd.DataFrame(columns=['标签','次数'])
cat = set()
for i in data.index:
for value in data.loc[i,"电影类型"].split("/"):
cat.add(value)
cat_list = list(cat)
biaoqian = pd.DataFrame(columns=['标签','次数'])
biaoqian['标签']= cat_list
biaoqian['次数']= np.zeros(len(cat_list))
for i in data.index:
for j in range(len(cat_list)):
if data.loc[i,"电影类型"].find(cat_list[j])!=-1:
biaoqian.loc[j,'次数'] = biaoqian.loc[j,'次数'] +1
biaoqian.sort_values(by='次数',axis=0,ascending=False,inplace=True)
newbiaoqian=biaoqian.iloc[:12,:]
list_12=newbiaoqian["标签"].values
data["电影类型_剧情"] = np.zeros(len(data))
data["电影类型_爱情"] = np.zeros(len(data))
data["电影类型_喜剧"] = np.zeros(len(data))
data["电影类型_冒险"] = np.zeros(len(data))
data["电影类型_奇幻"] = np.zeros(len(data))
data["电影类型_犯罪"] = np.zeros(len(data))
data["电影类型_动画"] = np.zeros(len(data))
data["电影类型_惊悚"] = np.zeros(len(data))
data["电影类型_动作"] = np.zeros(len(data))
data["电影类型_悬疑"] = np.zeros(len(data))
data["电影类型_科幻"] = np.zeros(len(data))
data["电影类型_家庭"] = np.zeros(len(data))
for i in data.index:
for j in range(len(list_12)):
if data.loc[i,"电影类型"].find(list_12[j])!=-1:
data.loc[i,"电影类型_"+list_12[j]] = 1
data["电影类型_剧情"].value_counts()
data["电影类型_爱情"].value_counts()
data["电影类型_喜剧"].value_counts()
data["电影类型_冒险"].value_counts()
data["电影类型_奇幻"].value_counts()
data["电影类型_犯罪"].value_counts()
data["电影类型_动画"].value_counts()
data["电影类型_惊悚"].value_counts()
data["电影类型_动作"].value_counts()
data["电影类型_悬疑"].value_counts()
data["电影类型_科幻"].value_counts()
data["电影类型_家庭"].value_counts()
biaoqian.to_excel("result1-1.xlsx",index =False)
#1-2
daoyan = data["导演"].value_counts()
daoyan.iloc[:10].to_excel("result1-2.xlsx")
names=daoyan.index
data["导演(编号)"] = data["导演"]
for i in range(len(names)):
data['导演(编号)'].replace(names[i],value=i,inplace=True)
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib
f, ax = plt.subplots(figsize=(220, 110))#15,10
sns.set(font_scale=2)
sns.set_style("darkgrid")
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
# 为了坐标轴负号正常显示。matplotlib默认不支持中文,设置中文字体后,负号会显示异常。
需要手动将坐标轴负号设为False才能正常显示负号。
matplotlib.rcParams['axes.unicode_minus'] = False
sns.countplot(y='导演',data=data,order=data["导演"].value_counts().index)
plt.savefig('result1-2.png')
data["国家"].value_counts()
guojia = pd.DataFrame(columns=['国家','次数'])
guojia_cat = set()
for i in data.index:
for value in data.loc[i,"国家"].split(" / "):
guojia_cat.add(value)
guojia_cat_list = list(guojia_cat)
guojia['国家']= guojia_cat_list
guojia['次数']= np.zeros(len(guojia_cat_list))
for i in data.index:
for j in range(len(guojia_cat_list)):
if data.loc[i,"国家"].find(guojia_cat_list[j])!=-1:
guojia.loc[j,'次数'] = guojia.loc[j,'次数'] +1
guojia.sort_values(by='次数',axis=0,ascending=False,inplace=True)
newguojia = guojia
sns.set(font_scale=10)
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
# 为了坐标轴负号正常显示。matplotlib默认不支持中文,设置中文字体后,负号会显示异常。
需要手动将坐标轴负号设为False才能正常显示负号。
matplotlib.rcParams['axes.unicode_minus'] = False
fig, ax = plt.subplots(figsize=(120, 70))
plt.xticks(rotation=270)
plt.plot(newguojia['国家'].values,newguojia['次数
'].values,marker='o',markersize=50,linewidth=10.0)
plt.xlabel(u"国家")
plt.ylabel(u'次数')
#plt.xticks(np.arange(0,1.1,0.1))
plt.savefig('result1-3.png')
plt.show()
temp_guojia=newguojia.iloc[:5,:]
sns.set(font_scale=2)
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
# 为了坐标轴负号正常显示。matplotlib默认不支持中文,设置中文字体后,负号会显示异常。
需要手动将坐标轴负号设为False才能正常显示负号。
matplotlib.rcParams['axes.unicode_minus'] = False
get_ipython().run_line_magic('config', "InlineBackend.figure_format = 'png'")
#绘制变量类型饼状图
fig = plt.figure(figsize=(15,15))
Num =np.sum(temp_guojia["次数"].values)
#单个数据
count = temp_guojia["次数"].values
#数据标签
labels = temp_guojia["国家"].values
#各区域颜色
#colors = ['orange','yellow','green','blue','red']
colors = ["#60A9A6","#FDDEDE","#FFBA92","#F5FEC0","#FF8080"]
#数据计算处理
sizes =
[count[0]/Num*100,count[1]/Num*100,count[2]/Num*100,count[3]/Num*100,count[4]/Num*100]
#设置突出模块偏移值
expodes = (0,0,0,0,0.2)
#设置绘图属性并绘图
plt.pie(sizes,explode=expodes,labels=labels,shadow=True,colors=colors,autopct='%.2f%%')
## 用于显示为一个长宽相等的饼图
plt.axis('equal')
plt.savefig('result1-3-2.png')
plt.show()
newguojia.to_excel("result1-3.xlsx",index =False)
temp=newguojia.iloc[:11]
#国家编码
list_11=temp["国家"].values
data["国家_美国"] = np.zeros(len(data))
data["国家_英国"] = np.zeros(len(data))
data["国家_日本"] = np.zeros(len(data))
data["国家_中国香港"] = np.zeros(len(data))
data["国家_中国大陆"] = np.zeros(len(data))
data["国家_法国"] = np.zeros(len(data))
data["国家_德国"] = np.zeros(len(data))
data["国家_韩国"] = np.zeros(len(data))
data["国家_意大利"] = np.zeros(len(data))
data["国家_加拿大"] = np.zeros(len(data))
data["国家_中国台湾"] = np.zeros(len(data))
for i in data.index:
for j in range(len(list_11)):
if data.loc[i,"国家"].find(list_11[j])!=-1:
data.loc[i,"国家_"+list_11[j]] = 1
data["国家_美国"].value_counts()
data["国家_英国"].value_counts()
data["国家_日本"].value_counts()
data["国家_中国香港"].value_counts()
data["国家_中国大陆"].value_counts()
data["国家_法国"].value_counts()
data["国家_德国"].value_counts()
data["国家_韩国"].value_counts()
data["国家_意大利"].value_counts()
data["国家_加拿大"].value_counts()
data["国家_中国台湾"].value_counts()
data.to_excel("bianma2-2.xlsx")
import seaborn as sns
f, ax = plt.subplots(figsize=(220, 110))#15,10
sns.set(font_scale=20)
sns.set_style("darkgrid")
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
# 为了坐标轴负号正常显示。matplotlib默认不支持中文,设置中文字体后,负号会显示异常。
需要手动将坐标轴负号设为False才能正常显示负号。
matplotlib.rcParams['axes.unicode_minus'] = False
ax.set_xticklabels(ax.get_xticklabels(), rotation=45)
sns.countplot(x="上映年份",data=data)
ax.plot()
plt.savefig('result2-1.png')
nianfen=data["上映年份"].value_counts()
nianfen.sort_index(inplace=True)
nianfen.index
#Spearman相关系数
temp_list = ["评分","评论人数","国家","导演","电影类型"]
data[temp_list]
#分别查看评分和评论人数的分布情况
sns.set(font_scale=13)
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
# 为了坐标轴负号正常显示。matplotlib默认不支持中文,设置中文字体后,负号会显示异常。
需要手动将坐标轴负号设为False才能正常显示负号。
matplotlib.rcParams['axes.unicode_minus'] = False
fig = plt.figure(figsize=(110,50))
ax1 = fig.add_subplot(121)
sns.distplot(data['评分'],ax=ax1,hist=True,kde=True,rug=False, kde_kws=dict(linewidth=8))
ax1.tick_params(bottom=False, top=False, left=True, right=False)
ax2 = fig.add_subplot(122)
sns.distplot(data['评论人数'],ax=ax2,hist=True,kde=True,rug=False, kde_kws=dict(linewidth=8))
ax2.tick_params(bottom=False, top=False, left=True, right=False)
plt.savefig('fig2-2.png')
plt.show()
plt.figure(figsize=(100,100))
sns.set(font_scale=20)
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
# 为了坐标轴负号正常显示。matplotlib默认不支持中文,设置中文字体后,负号会显示异常。
需要手动将坐标轴负号设为False才能正常显示负号。
matplotlib.rcParams['axes.unicode_minus'] = False
sns.heatmap(data[["评分","评论人数
"]].corr(method='spearman'),linewidths=0.05,vmax=1.0,vmin=-1, square=True,linecolor='white',
annot=True)
#plt.title('斯皮尔曼热力图')
plt.savefig('fig2-3.png')
plt.show()
print(np.max(data['评分'].values),np.min(data['评分'].values))
fig = plt.figure(figsize=(25,25))
n,bins,patches=plt.hist(data['评分'].values,6)
#评分离散化
data["评分等级"]=pd.cut(data["评分"],bins = 6,right=True,labels=[1,2,3,4,5,6])
data.to_excel("bianma2-2.xlsx")
# 国家和评分是否有关
x = []
for country in newguojia["国家"].values[:18]:#取前18个国家
temp = []
for i in data.index:
if data.loc[i,"国家"].find(country) != -1:
temp.append(data.loc[i,'评分'])
x.append(temp)
len(x)
sns.set(font_scale=5)
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
# 为了坐标轴负号正常显示。matplotlib默认不支持中文,设置中文字体后,负号会显示异常。
需要手动将坐标轴负号设为False才能正常显示负号。
matplotlib.rcParams['axes.unicode_minus'] = False
fig = plt.figure(figsize=(60,60))
ax1 = fig.add_subplot(211)
plt.boxplot(x[:9], labels=newguojia['国家'].values[:9],notch = False,sym = '*',patch_artist =
True,boxprops = {'color':'orangered','facecolor':'pink'})
ax1.tick_params(bottom=False, top=False, left=True, right=False)
ax2 = fig.add_subplot(212)
plt.boxplot(x[9:18], labels=newguojia['国家'].values[9:18],notch = False,sym = '*',patch_artist =
True,boxprops = {'color':'orangered','facecolor':'pink'})
ax1.tick_params(bottom=False, top=False, left=True, right=False)
#plt.tight_layout()
#plt.subplots_adjust(wspace=0.58, hspace=0.45)
plt.savefig('result2-2_guojia.png')
#电影类型和评分是否有关
y = []
for leixing in biaoqian["标签"].values:#取所有类型
temp = []
for i in data.index:
if data.loc[i,"电影类型"].find(leixing) != -1:
temp.append(data.loc[i,'评分'])
y.append(temp)
len(y)
sns.set(font_scale=5)
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文
# 为了坐标轴负号正常显示。matplotlib默认不支持中文,设置中文字体后,负号会显示异常。
需要手动将坐标轴负号设为False才能正常显示负号。
matplotlib.rcParams['axes.unicode_minus'] = False
fig = plt.figure(figsize=(60,60))
ax1 = fig.add_subplot(311)
plt.boxplot(y[:9], labels=biaoqian['标签'].values[:9],notch = False,sym = '*',patch_artist =
True,boxprops = {'color':'orangered','facecolor':'#60A9A6'})
ax1.tick_params(bottom=False, top=False, left=True, right=False)
ax2 = fig.add_subplot(312)
plt.boxplot(y[9:18], labels=biaoqian['标签'].values[9:18],notch = False,sym = '*',patch_artist =
True,boxprops = {'color':'orangered','facecolor':'#60A9A6'})
ax1.tick_params(bottom=False, top=False, left=True, right=False)
ax2 = fig.add_subplot(313)
plt.boxplot(y[18:27], labels=biaoqian['标签'].values[18:27],notch = False,sym = '*',patch_artist =
True,boxprops = {'color':'orangered','facecolor':'#60A9A6'})
ax1.tick_params(bottom=False, top=False, left=True, right=False)