查看原文
其他

DOTA2先干掉中路一塔后有多大胜算?

数据冰山 2022-04-11

上回数据冰山发布的《TI7伤害之王》《TI7小组赛英雄数据报告》收到冰友反馈:

  • 游戏数据接口API如何调用?我没有编程基础,感觉很难的样子。

  • 能不能给一些具体的例子,能一步一步学着操作的那种。

  • 内容可以再丰富一点吗?

我是过来人,道理我都懂。大家其实是希望我给一个故事完整、过程清晰、内容详实的DOTA2数据分析例子,这样学起来才会有顺藤摸瓜的感觉,比起摸着石头过河,能够少踩一些坑。

既然如此,我也只好收拾一下自己的懒癌,再满足大家一次。

本文叙述结构按照数据分析师的工作流程来:

  1. 提一个值得分析的问题(中路一塔到底有多重要?)

  2. 获取数据源(手把手演示如何使用python调用API获取需要的数据)

  3. 确定方法论(统计推断statistical inference),处理数据,得出结论

【注意:在数据分析师的实际工作过程中,顺序可能颠倒,也可能重复多次】

一、提一个好问题

会提问、提好问,是数据分析师最重要的技能之一。

大家平时听讲座,经常看到演讲者眼冒精光的对某个提问者说:“你这个问题提的非常好!很有水平!(加鸡腿)”。演讲者觉得问题好,是因为这个问题触及了事情的本质,回答好这个问题,就可以把事情说清楚。

和他问自答的演讲者相比,自问自答的数据分析师自由度更高,更需要借一双慧眼,在纷繁复杂的数据和千头万绪的可能性之中,找到最接近真相的那些问题。

本文提出的问题是:DOTA2这款免费游戏的中路一塔有多重要?

喜欢看比赛的朋友,对这个问题应该不陌生。主播解说比赛时经常讲:这个中路一塔绝对不能放!这个塔放了之后,视野黑一大片,活动范围减小,打钱空间被压缩...就不好打了!那么,主播们说的对吗?如何衡量中路一塔的重要性?

在DOTA2的世界里,所谓「重要」,只有两个字:能赢。比如刀塔中最重要的建筑毫无疑问是基地——因为基地一炸,比赛就结束了。如果我们可以把「先拆掉敌方中路一塔」和「比赛胜负」联系起来,就可以得出答案。按这个思路,对每场比赛,我们需要的数据是:

  1. 哪一方先拆掉敌方中路一塔

  2. 哪一方赢得了比赛

二、获取数据源

如何获取一场比赛的「拆塔信息」和「比赛胜负」?

上篇文章讲过,可以调用OPENDOTA提供的API来获取公开比赛数据。查阅API接口文档后,发现有一个名叫matches的api提供了一场比赛(match)的详细信息。我们需要的数据很可能在api返回的结果里。

我们不妨找一场比赛调用这个API试一下(反正又不要钱),看看它到底提供了哪些数据。以刚刚结束的长沙MDL MAJOR最后一场比赛为例(LGD夺冠那场),它的比赛编号(也就是调用api要传入的参数:match_id)是3903099199。

同学们不要紧张,现在还不用写代码。

这种webapi是可以在浏览器中调用的。只需要按API的接口说明构建出网址api.opendota.com/api/ma,然后把链接复制到你常用的浏览器中,按回车就可以得到结果:

为什么数据这么多?平时打完一局DOTA2,赛后统计数据没这么多啊?

同学们不要紧张。Opendota提供的matches接口,不仅返回了「基础赛后统计数据」,还包含了许多「通过解析录像得到的游戏中数据」。以防御塔数据为例,基础的赛后统计数据只能告诉你比赛结束时,双方队伍的防御塔存亡状态(哪些拆掉了,哪些还在);而解析录像得到的游戏中数据,可以告诉你每座塔是什么时候被谁拆掉的。

如果你愿意,你甚至可以通过解析录像知道拆塔的过程中,每一个英雄每一下A出了多少伤害。也就是说,DOTA2这款游戏的数据源很开放(其他类DOTA游戏没法比),这也正是我在市面上已经有非常多数据分析入门教程的前提下,执意要写「DOTA2数据分析入门」教程的原因——因为对大家来讲,那些教材使用的数据源都不对口,学起来很容易半途而废(特别是基础不好的朋友)。而DOTA2这款游戏内涵丰富,可以分析的维度很多,如果你本身是一名刀塔玩家,使用DOTA2数据源来学习数据分析,学习过程一定会很愉快。

比如,当你看到上图中的「"radiant_win":false」时,你一定会知道radiant表示天辉,所以radiant_win就是天辉胜利,合起来就是:天辉胜利为假,那就是夜魇(Dire)获胜咯!(如果不放心,你可以找第三方数据产品验证一下)

是不是很简单?

接下来我们在API返回的结果中寻找第二个数据「拆塔信息」。经过一番折腾(比如搜索关键字"tower"或者"building"),我们可以发现数据出现了一些奇怪的东西:

  • npc_dota_goodguys_tower1_mid

  • npc_dota_badguys_tower1_mid

  • npc_dota_goodguys_tower2_bot

  • npc_dota_goodguys_tower3_top

tower1是什么鬼?一塔?mid\bot\top是中塔\下塔\上塔?那goodguys和badguys是不是天辉和夜魇???

是的,上面的猜测都是对的,V社就是这么任性(不好好用radiant,还要搞个goodguys...)。

所以,上图中的两条拆塔信息是:

  1. 名叫npc_dota_hero_gyrocopter(矮人直升机)的单位,于20分10秒,拆掉(反补)了天辉方的中路一塔。

  2. 名叫npc_dota_hero_gyrocopter(矮人直升机)的单位,于20分37秒,拆掉了夜魇方的中路一塔。

如果你不放心,仍然可以用第三方数据产品(DOTABUFF、OPENDOTA、刀魔数据等)来验证数据的准确性:

OK,到现在为止,我们终于获取了LGD对阵VGJ.S的第三局所有想要的信息:夜魇方先拆掉天辉方的中路一塔,夜魇获胜。

但是,使用浏览器调用接口,人工统计信息的操作会很麻烦(比如你想查询100场比赛的信息,估计眼睛都要看瞎)。

接下来我们必须开始写代码了。关于代码有两点说明:

  • 本系列教程不会教大家写代码,请自行学习python、requests、notebook等编程知识(自律且时间充裕的朋友,可以Google搜关键字自学;基础太差或者想有人一起学的朋友,可以考虑报网课,比如「优达学城(Udacity)」)

  • 文中用到的所有代码,都会放在GitHub上(repository叫dota2_analysis_tutorial)。给大家作为参考~

写代码的时候,我们可以再简化一下,把「拆塔和比赛胜负的联系」用一个bool类型表示。比如我们可以写一个名叫is_destroy_mid_tower_induce_win的函数,对每一场比赛(用match_id标识)返回:

  • True,表示先拆掉敌方中路一塔的队伍,取得了胜利

  • False,表示先拆掉地方中路一塔的队伍,遭受了失败

  • None,表示获取不到数据(录像损坏或者解析出错)

三、处理数据,得出结论

孤证不立,一场比赛的情况不足以反映规律,我们需要看更多比赛的数据。DOTA2进入7.0时代以来,一共打了13574场职业比赛(可用下图的SQL在OpenDota - Dota 2 Statistics上查询)。

难道我们要把1万3千多场比赛的信息都弄下来?这样做确实可以,但是太耗时间了——OpenDota提供的API限制访问速度是1分钟60次,也就是需要4个小时才能获取这些比赛的信息(而且代码没有处理网络异常,很有可能跑到一半就GG了,重来又是4小时...)

怎么办?这个时候就需要一些统计学知识了。我们先随机抽取200场比赛看看情况。

200场比赛的结果是这样的:

  • 93场比赛无法获得「拆塔信息」数据,属于无效样本。

  • 剩下的107场比赛中,先拆掉敌方中一塔获胜的场次是67场,67/107=62.6%。

62.6%!意思是只要先拆掉敌方中一塔,就有6成以上的胜率?不好说,因为这只是107场比赛的数据(总共有1万多场比赛),比如我们再重新抽107场比赛,结果很可能会不一样。那么问题来了,这个62.6%的可信度有多高?

这需要用到「统计推断」的知识(推荐一本书《OpenIntro Statistics》)。我们采样的每场比赛之间相互独立,同时正负样本的数量都大于10(说明采样结果的分布没有严重偏曲)。根据「中心极限定理」,采样结果的分布近似服从正态分布。

先算出标准差为0.047,然后算出95%置信区间为[53.4%, 71.8%]。也就是说,根据107场抽样比赛来看,我们有95%的把握:先拆掉敌方中路一塔的队伍,获胜概率在53.4%~71.8%之间。

但是这个结论太粗糙了,只能说明先拆掉中路一塔是件好事(获胜概率>50%),但无法说清楚这件事到底有多好(53%和71%的差距还是很大的)。

为了缩小置信区间的宽度使估计值更精确,我们可以增加样本数量:

  • 随机抽取223场比赛(先拆掉中路一塔的队伍获胜场次为142,142/223=63.7%),获胜概率的95%置信区间为[57.4%, 70%]

  • 随机抽取528场比赛(先拆掉中路一塔的队伍获胜场次为347,347/528=65.7%),获胜概率的95%置信区间为[61.7%, 69.8%]

  • 随机抽取1979场比赛(先拆掉中路一塔的队伍获胜场次为1280,1280/1979=64.7%),获胜概率的95%置信区间为[62.6%, 66.8%]

  • ...

不需要更多的样本了——当样本数量为2000场时,我们已经可以很自信的说(95%的概率):先拆掉中路一塔的队伍,具有一定的优势,获胜概率在62.6%~66.8%之间。

那么问题又来了,这64.7%左右的胜率算高吗?(老队长:我就问你有什么影响?)到目前为止,我们可以用于比较的参考值只有「先拆掉基地的胜率为100%」,没啥意义,但我们完全可以用相同的方法论给出更多、更有意义的benchmark(基准):【以下都是95%置信区间】

  • 拿到第一个肉山盾的队伍,获胜概率是[73.5%,77.3%]

  • 拿到一血的队伍,获胜概率是[52.7%, 57.1%]

  • 先拆掉第一座防御塔(上\中\下任意一座)的队伍,获胜概率是[59.4%,63.7%]

有了对比,我们就可以得出结论:中路一塔的战略地位确实高于边路一塔(只要先于敌方拆掉中一塔,就能建立优势,提升胜率),但也没有特别重要(不如第一个肉山盾)。

写到这里,一个完整的数据分析例子就算完成了。但「完整」并不代表「完结」:

  1. 从深度上来讲:大家可以对比分析中一塔被拆掉前后,有没有影响队伍的打钱速度、活动范围?找出中一塔具体的影响因素,从而在实战中调整策略。

  2. 从广度上来讲:大家可以加入战队、版本号等维度,对样本进行拆分,描述中一塔战略地位的变化和队伍风格。

当然,我觉得更好的学习方法是:从兴趣出发,找到自己认为有意义问题,用相同的方法论处理数据,得出结论。

特别鸣谢:何求知


点击查看历史文章,揭开冰山水面下更多的数据秘密!



知乎专栏:数据冰山

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存