V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
metaquant
V2EX  ›  分享发现

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

  •  
  •   metaquant · 2017-09-20 12:33:06 +08:00 · 8072 次点击
    这是一个创建于 2624 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    一、数据描述

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

    • movie_name:进入榜单的电影的名称;
    • rank:该电影在榜单中的排名;
    • director:该电影的导演;
    • year:电影上映的年份;
    • time:电影的时长;
    • score:电影的豆瓣评分;
    • score_num:参与评分的总人数,侧面反映了电影的大众与流行程度;
    • stars:平均星级,使用豆瓣电影上给出的各个星级评分所占的比例,计算加权平均的星级,可以判断电影的总体评分情况;
    • total_star:总星级,综合了电影的星级与评分人数两年指标,为平均星级与参与评分总人数的乘积;
    • std:星级标准差,使用计算出来的平均星级,可以计算所有星级评分的标准差,这反映了这部电影评分的一致性,如果标准差较大,则反映这部电影的评分比较两极分化

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

    二、初步探索性分析

    我使用 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
    34 条回复    2017-09-26 11:22:55 +08:00
    zeninger
        1
    zeninger  
       2017-09-20 13:05:01 +08:00
    感谢分享,加个 star
    mrjoel
        2
    mrjoel  
       2017-09-20 13:09:38 +08:00 via iPhone
    👍
    codexu
        3
    codexu  
       2017-09-20 13:14:57 +08:00
    👍
    wellsc
        4
    wellsc  
       2017-09-20 13:35:24 +08:00 via iPhone
    👍
    izgnod
        5
    izgnod  
       2017-09-20 13:44:27 +08:00 via Android
    👍
    ctsed
        6
    ctsed  
       2017-09-20 14:08:20 +08:00
    👍
    yuang
        7
    yuang  
       2017-09-20 14:29:39 +08:00 via Android
    👍
    beyoung
        8
    beyoung  
       2017-09-20 14:32:43 +08:00
    👍
    SkyKoo
        9
    SkyKoo  
       2017-09-20 14:38:59 +08:00
    👍
    cqcn1991
        10
    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
        11
    fyl00  
       2017-09-20 14:59:53 +08:00
    楼主,你有没有发现豆瓣评分并没有其他指标,就是所有打分的平均分。你算出来的分*2 基本上就等于豆瓣的分了,而「用各个星级所占的比例对星级进行加权平均」其实就是平均分了
    metaquant
        12
    metaquant  
    OP
       2017-09-20 15:05:39 +08:00
    @fyl00 是的,豆瓣的评分机制确实比较简单粗暴,我这里重新算只是为了小数位数更精确,方便排序。其实更有意思的是豆瓣的电影排序,比如同样评分那个电影排在前面?显然豆瓣考虑了评分人数的影响,但并没有公布具体的算法。
    metaquant
        13
    metaquant  
    OP
       2017-09-20 15:10:25 +08:00
    @cqcn1991 感谢,写的时候参考了你的文章
    mingoahz
        14
    mingoahz  
       2017-09-20 15:12:23 +08:00
    突然发现墨镜王的电影名字都是四个字
    metaquant
        15
    metaquant  
    OP
       2017-09-20 15:16:13 +08:00
    @mingoahz 观察敏锐,也许可以做一个电影名字长度对电影评分影响的分析,哈哈
    Chingim
        16
    Chingim  
       2017-09-20 15:34:57 +08:00 via Android
    战狼的配图和文字说明不符。图片中,五星的比例 25%,一星的比例 5%


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


    黑人问号脸
    nightwind
        17
    nightwind  
       2017-09-20 16:07:24 +08:00
    看到好评之后,再看电影,得出好评的机率更大
    看到差评之后,再看电影,得出差评的机率更大
    那么结果就是评分并不能公平的反映电影真实质量
    对嘛 lz
    UnPace
        18
    UnPace  
       2017-09-20 16:11:24 +08:00
    👍
    metaquant
        19
    metaquant  
    OP
       2017-09-20 16:13:51 +08:00
    @Chingim 这里的表述不太准确,应是五星与一星的比例较三星四星比例要少
    metaquant
        20
    metaquant  
    OP
       2017-09-20 16:17:20 +08:00
    @nightwind 一般来说,看到很多差评就不会去看电影了吧,估计也没有什么评论的兴趣。因为评分只是一个平均值,所以“只看评分”确实不能准确地反映电影的质量。
    zaxlct
        21
    zaxlct  
       2017-09-20 16:43:24 +08:00 via Android
    👍
    schema
        22
    schema  
       2017-09-20 16:45:37 +08:00 via Android
    👍
    leeeric
        23
    leeeric  
       2017-09-20 16:58:14 +08:00
    能不能分析到评星的时间段?
    结合该片的上映时段,可以判断是否是现象级影片或者是水军助力?
    比如一个片子在刚刚上映就获得大量的 4、5 星好评,但后期以 3 星及以下居多,就可以认为有水军营销的嫌疑。
    而对于上映期后期甚至下线后仍然有高分评价的,应该是经得起时间考验,或者说至少排出了营销影响的真实数据。
    metaquant
        24
    metaquant  
    OP
       2017-09-20 17:22:54 +08:00
    @leeeric 要做这种时间序列上的分析,需要定期地爬取、存储与分析数据,工作量很大,而且要搜集比较长时间才有比较的意义。

    关于水军刷分,豆瓣与 IMDB 都有相应的应对办法,比如注册时间长短,评价电影数量的多少等,目前看来效果似乎还可以。

    由于豆瓣与 IMDB 的 Top250 榜单都要求评论数达到一定数量才能入选,所以新上映的电影本来也很难进入榜单,能进入的基本都是积累了一定的观影人数的电影。
    CEBBCAT
        25
    CEBBCAT  
       2017-09-20 22:19:00 +08:00 via Android
    怎么记得之前看过,连属性名都一样
    sugod
        26
    sugod  
       2017-09-20 22:56:15 +08:00
    很早之前看到过 IMDB 的算法,
    知乎
    https://www.zhihu.com/question/19746144

    IMDB 传送门
    http://www.imdb.com/help/show_leaf?votestopfaq&pf_rd_m=A2FGELUUNOQJNL&pf_rd_p=2398042102&pf_rd_r=1QFR14S6CRDSEPT7XT52&pf_rd_s=center-1&pf_rd_t=15506&pf_rd_i=top&ref_=chttp_faq


    How do you calculate the rank of movies and TV shows on the Top 250 Rated Charts?
    The following formula is used to calculate the Top Rated 250 titles. This formula provides a true 'Bayesian estimate', which takes into account the number of votes each title has received, minimum votes required to be on the list, and the mean vote for all titles:

    weighted rating (WR) = (v ÷ (v+m)) × R + (m ÷ (v+m)) × C

    Where:

    R = average for the movie (mean) = (Rating)
    v = number of votes for the movie = (votes)
    m = minimum votes required to be listed in the Top 250
    C = the mean vote across the whole report

    Please be aware that the Top Rated Movies Chart only includes theatrical features: shorts, TV movies, miniseries and documentaries are not included in the Top Rated Movies Chart. The Top Rated TV Shows Chart includes TV Series, but not TV episodes or Movies.
    metaquant
        27
    metaquant  
    OP
       2017-09-20 22:58:50 +08:00 via iPhone
    @CEBBCAT 我之前发过数据,这次只是加上了分析
    metaquant
        28
    metaquant  
    OP
       2017-09-20 23:00:08 +08:00 via iPhone
    @sugod 是的,IMDB 这个算法基于贝叶斯,还是比较科学的
    johnnie502
        29
    johnnie502  
       2017-09-21 05:21:26 +08:00
    我说怎么看着眼熟,拾人牙慧
    anson2416
        30
    anson2416  
       2017-09-21 08:57:58 +08:00 via iPhone
    做大数据分析 一般需要什么数学工学知识 不懂啊
    houskii
        31
    houskii  
       2017-09-21 11:23:06 +08:00
    👍
    leeeric
        32
    leeeric  
       2017-09-22 10:30:41 +08:00
    @metaquant 如果只是做着玩就无所谓了。如果是想真的对使用者有帮助,就要做这种啊。要知道豆瓣虽然有水军识别,但我怀疑他是自带友军和敌军的功能吧,当然我这种说法毫无根据,存粹瞎猜,但如果你能深入分析这些数据,没准儿真会发现什么“了不起”的事情呢?从人人都可以看到的数据中,获得所有人都没有猜到的结果,我认为这才是大数据的魅力所在。否则只是做又一个简单的统计而已,不好玩。
    Thinkerous
        33
    Thinkerous  
       2017-09-22 23:05:33 +08:00 via iPhone
    不错,除了数据收集,excel 处理也绰绰有余
    zxcasdqwe9
        34
    zxcasdqwe9  
       2017-09-26 11:22:55 +08:00
    @metaquant 口碑分化大举战狼 2 的例子完全是错误的吧,明明是 D 型的质量普通的片子怎么变成了 C 型了?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3307 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 12:38 · PVG 20:38 · LAX 04:38 · JFK 07:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.