对豆瓣电影 Top250 榜单的一些探索性分析

2017-09-20 12:33:06 +08:00
 metaquant

业余打发时间看电影是个不错的选择,但是如果看了一部无聊糟心的电影就得不偿失了,所以一些电影方面的榜单就出现了,可以为这些选择困难患者提供一个不错的指南,那些是经典是值得看的,而那些电影不值得你浪费一两个小时的时间。在电影榜单方面,国外最出名的自然是IMDB Top250,这个榜单收集了全球观众评选出的最好看的 250 部电影,国内最知名的榜单应该是豆瓣电影 Top250, 主要反映了国内观众的观影品味(虽然有人可能会说豆瓣的观影品味可能偏文艺一些)。对于这两个榜单,虽然对部分电影的排名多少有些争议,但是总体来说大家觉得对着这个榜单看电影,碰到烂片的概率还是较小的。

看到这些榜单,我们可能会有一些问题。比如,某个我最喜欢的导演有多少部电影进入榜单了?榜单中哪一年的电影最多?哪些电影的口碑较为统一,而哪些电影的口碑非常两极分化?为回答这些问题,我们需要对榜单中的信息进行一些搜集与整理。为了搜集这些信息,我使用爬虫爬取了豆瓣 Top250 榜单,并进行了一些探索性分析,这些分析可能可以回答你对榜单的某些疑问。

一、数据描述

我使用 Scrapy 爬取了豆瓣 Top250 榜单,针对每个电影,收集了以下十项指标,其中前七项是直接抓取获得,后三项则是间接计算得到:

搜集到的所有数据放在这个网址,你可以每一列进行排序,比如查看提名最高或最低的电影;也可以通过右上角的输入框进行筛选,比如想要搜诺兰的所有电影,只需要在输入框输入“克里斯托弗·诺兰”,你就可以看到榜单中诺兰的所有电影数据。

二、初步探索性分析

我使用 jupyter notebook 分析以上数据,所有的分析代码见这个网址 。首先,我们需要导入一些分析必需的库,做一些初始化设置:

# Import the required modules for the following codes

import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
import seaborn as sns
import pandas as pd
sns.set(style="white",color_codes=True)
%matplotlib inline
plt.rcParams['figure.figsize'] = (15,9.27)
plt.rcParams['font.size'] = 10.0
plt.rcParams['xtick.labelsize'] = 'large'
plt.rcParams['ytick.labelsize'] = 'large'

然后,我们导入数据,看看数据包含哪些信息:

df = pd.read_excel('output.xls',encoding="UTF-8")
df.head()

这个和我们之前描述的数据信息一致,数据默认是按照电影的排名升序排列的。

(一) 电影导演分析

通过导演来搜电影通常是个不错的主意,优秀的电影导演有鲜明个人风格,并总能控制电影的质量,降低我们看到烂片的可能性。我们首先关心的是,在豆瓣 Top250 榜单中哪些导演的入围电影最多?这很大程度上反映了该导演的水准。

directors = list(df['director'])
dir_dict = {x:directors.count(x) for x in set(directors)}
dir_df = pd.DataFrame.from_dict(dire,orient='index')
dir_df.columns = ['count']
dir_df.sort_values(['count'],axis=0,ascending=False,inplace=True)
dir_df['pert'] = dir_df['count']/250
dir_df[:20]

我们可以看到,按入围电影数量降序排列,排名前 20 名的电影导演是:

这个排名并不让人意外,排在前几名的都是大家耳熟能详的导演。如克里斯多弗·诺兰与宫崎骏在入围电影数量上并列第一,都为七部。斯皮尔伯格排第三,有六部,另外两名华人导演王家卫与李安分别入围五部与四部。下面我们分别看看这几位导演入围的电影有哪几部?

诺兰的电影:

宫崎骏的电影:

斯皮尔伯格的电影:

王家卫的电影:

李安的电影:

(二) 电影上映年份分析

豆瓣 Top250 榜单中年份最早的电影是 1931 年查理·卓别林的《城市之光》,最晚的 2016 年的《海边的曼彻斯特》与《疯狂动物城》。榜单中各个年份的电影数量各有不同,按该年份入围电影数量多少降序排列,前二十名的年份是:

year = list(df['year'])
year_dict = {x:year.count(x) for x in set(year)}
year_df = pd.DataFrame.from_dict(year_dict,orient='index')
year_df.columns = ['year_count']
new_year_df = year_df.sort_values(['year_count'],axis=0,ascending=False,inplace=False)
new_year_df['pert'] = year_df['year_count']/250
new_year_df[:20]

让我们 2010 年、1994 年 2009 年的几部电影分别是哪些吧。

2010 年:

1994 年:

2009 年:

下图可以让我们更加直观的看出各个年份入围电影的多少:

可以看出,入围豆瓣 Top250 榜单的大部分电影是 90 年代以后的电影,这可能是再之前的电影由于电影拍摄风格的不同,与现代观众已经有较在隔阂了。

另外,一个引起我们兴趣的问题是,随着年代发展电影的质量或者说评分是否有显著提高,这个可以通过比较各个年份上映电影的平均分来有一个直观的了解。

通过柱状图,我们可以发现电影的评分似乎并没有随着年代的向前推移而增长,各个年份的评分大致是差不多的(由于榜单中电影数量有限,这个趋势评价应只适用于榜单中的电影,推广到所有年份的电影并不一定能够成立)。

三、电影口碑分析

豆瓣评分作为一个平均指标,虽然能在一定程度上反映电影的质量,但是在很多时候不能提供该电影的全面信息。比如,一个我们经常关心的问题是:一部电影的口碑是否一致,一般而言,同样评分的电影,如果某一部电影的口碑更为一致,即大家都说好,那么他是好电影的可能性也就越高。那么,我们如何去衡量某部电影口碑的一致性了?其实只需要仔细观察豆瓣给出的各个星级评分的分布比例,我们就能找到答案。

我们可以看到《肖申克的救赎》的评分为 9.6 分,其中从五星至一星的人数占总评分人数的比例分别为 82.1%,15.7%,2.0%,0.1%与 0.1%,可以看出绝大部分人给了这部电影四星以上的评价,这是口碑非常一致的电影中的典型。让我们再看看口碑一致的烂片典型:

可以看到《深夜食堂》的一星比例高达 81.9%,是近年来少有大家一致认为非常烂的电影,在口碑一致性程度上,它恐怕是创纪录的。从以上我们可以看到,一部口碑一致的好片,其评分的形状大致是 P 形,即从五星至一星逐渐递减。口碑一致的烂片其评分大致是 b 形,从五星到一星逐渐增加,最烂的就是 L 形了,一星比例占了绝大部分。

对于以上两种类型电影,选择上并没有什么难度。因为口碑一致可以让我们很好地确定这部电影是好片还是烂片,但是对于那些口碑不太一致的电影,选择就变得更加困难了。

如截止到目前的国产电影票房冠军《战狼 2 》实际上是一部分口碑分化较大的电影,我们可以看出它的评分形状大致呈 C 形,即五星与一星都较少,中间星级所占的比例则较多。

为了量化我们上面的观察结果,我们需要计算两个指标:

  1. 平均星级:用各个星级所占的比例对星级进行加权平均,求出加权平均星级,作为衡量电影质量的指标。之所以不使用豆瓣的评分指标,是因为豆瓣评分综合考虑了电影的评价、评分人数等指标,并不只单纯衡量了电影质量;
  2. 星级标准差:在平均星级的基础上,以各个星级所占比例为权重,我们可以计算出星级评价的标准差,这个指标可以量化电影口碑的不一致程度,标准差越大,则电影的口碑越不一致。

在我们的数据中,分别用 wa_star 与 wa_star_std 来衡量两个指标。我们可以看看榜单中口碑最一致的五部电影分别是:

口碑最不一致的五部分电影分别是:

榜单中的这五部分电影仍然是非常不错的电影,但却由于各种各样的原因,其评分多有争议。如《穆赫兰道》由于过于深奥,在口碑上两极分化严重,一部分人引为神片,认为是比《盗梦空间》更为优秀的关于人类意识结构的电影,而另外一些人则认为导演故弄玄虚,需要对着说明书才能看懂的电影不是好电影。

(一) 电影评分与其口碑一致性的关系

为了更直观的理解电影的评分和他的口碑一致度的关系,我们可以以电影的平均星级为横轴,电影的星级标准差为纵轴绘制散点图如下:

我们可以清楚的看到,随着电影平均星级的增加,电影的评分差异度随之下降,也就是说,评分越高的电影大家的口碑就越一致。此外,也可以看出,随着电影评分的增加,标准差收敛的速度也在加快。我们可以做一个简单的回归来看看两者之间的量化关系:

def reg(y,yname,xname,*args):
    import statsmodels.api as sm
    x = np.vstack((args)).T
    mat_x = sm.add_constant(x)
    res = sm.OLS(y,mat_x).fit()
    print(res.summary(yname=yname,xname=['cosnt']+xname))

# was_sq is the squre of the weighted average star rating

was_sq = was**2
reg(wa_std,'wa_star_std',['was','was_sq'],was,was_sq)

首先定义一个线性回归的辅助函数,对 statsmodels 模块的线性回归函数做了一个包装,然后引入了 was_sq 变量,它是平均星级的平方。回归的结果是:

四、参考

  1. 数据源地址: https://data.metaquant.org/table/douban.html
  2. 项目代码: https://github.com/sorrowise/douban_top250
  3. 电影网站评分机制: https://einverne.github.io/post/2017/04/movie-score.html
  4. 豆瓣的电影评分靠谱吗?: https://zhuanlan.zhihu.com/p/24815577
  5. 豆瓣 Top250 榜单: https://movie.douban.com/top250
8060 次点击
所在节点    分享发现
34 条回复
zeninger
2017-09-20 13:05:01 +08:00
感谢分享,加个 star
mrjoel
2017-09-20 13:09:38 +08:00
👍
codexu
2017-09-20 13:14:57 +08:00
👍
wellsc
2017-09-20 13:35:24 +08:00
👍
izgnod
2017-09-20 13:44:27 +08:00
👍
ctsed
2017-09-20 14:08:20 +08:00
👍
yuang
2017-09-20 14:29:39 +08:00
👍
beyoung
2017-09-20 14:32:43 +08:00
👍
SkyKoo
2017-09-20 14:38:59 +08:00
👍
cqcn1991
2017-09-20 14:53:03 +08:00
原作路过...

关于豆瓣电影评分差异的分析, https://www.douban.com/note/624372911/
豆瓣和 IMDB 电影评分的比较, https://www.douban.com/note/599456964/

最后,关于战狼 2 的分析, https://www.v2ex.com/t/380084#reply106
fyl00
2017-09-20 14:59:53 +08:00
楼主,你有没有发现豆瓣评分并没有其他指标,就是所有打分的平均分。你算出来的分*2 基本上就等于豆瓣的分了,而「用各个星级所占的比例对星级进行加权平均」其实就是平均分了
metaquant
2017-09-20 15:05:39 +08:00
@fyl00 是的,豆瓣的评分机制确实比较简单粗暴,我这里重新算只是为了小数位数更精确,方便排序。其实更有意思的是豆瓣的电影排序,比如同样评分那个电影排在前面?显然豆瓣考虑了评分人数的影响,但并没有公布具体的算法。
metaquant
2017-09-20 15:10:25 +08:00
@cqcn1991 感谢,写的时候参考了你的文章
mingoahz
2017-09-20 15:12:23 +08:00
突然发现墨镜王的电影名字都是四个字
metaquant
2017-09-20 15:16:13 +08:00
@mingoahz 观察敏锐,也许可以做一个电影名字长度对电影评分影响的分析,哈哈
Chingim
2017-09-20 15:34:57 +08:00
战狼的配图和文字说明不符。图片中,五星的比例 25%,一星的比例 5%


文字说明:我们可以看出它的评分形状大致呈 C 形,即五星与一星都较少,中间星级所占的比例则较多。


黑人问号脸
nightwind
2017-09-20 16:07:24 +08:00
看到好评之后,再看电影,得出好评的机率更大
看到差评之后,再看电影,得出差评的机率更大
那么结果就是评分并不能公平的反映电影真实质量
对嘛 lz
UnPace
2017-09-20 16:11:24 +08:00
👍
metaquant
2017-09-20 16:13:51 +08:00
@Chingim 这里的表述不太准确,应是五星与一星的比例较三星四星比例要少
metaquant
2017-09-20 16:17:20 +08:00
@nightwind 一般来说,看到很多差评就不会去看电影了吧,估计也没有什么评论的兴趣。因为评分只是一个平均值,所以“只看评分”确实不能准确地反映电影的质量。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/392219

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX