"叶祁夏季赛循环赛清梦 VS Simon"这个名字,乍看只是一场普通的电竞循环赛对阵记录。但如果把视角从“看比赛”切换到“拆比赛”,会发现这场对局真正值得讨论的,不是谁赢了谁输了,而是我们如何用数据把一场比赛的胜负逻辑还原出来。
很多观众看比赛只关注击杀数和最终比分,但职业战队的复盘教练会从资源配置、视野布控、技能时间差、发育曲线这类细节里找问题。普通玩家和战队之间的认知差距,往往不是操作差了多少,而是复盘深度的差距。本文就以“清梦 VS Simon”这场循环赛为背景,整理一套完整的电竞赛事数据复盘方法:从数据获取、清洗、分析到可视化,每一步都给出可执行代码,帮助你把一场比赛的录像变成可量化、可借鉴的技术资料。
无论你是数据分析初学者、电竞爱好者,还是想给战队做技术支持的开发者,这篇文章都适用。读完你会掌握一套通用的赛事分析流水线,并且知道怎么用 Python 快速搭建它。
1. 这篇文章真正要解决的问题
先想一个很实际的问题:当你拿到一场比赛的录像或数据表时,第一反应是什么?大多数人会直接拉到最后看比分,然后随口评价一句“某某选手这把打得不好”。但“哪里不好”“为什么不好”“从第几分钟开始不好”,这些问题如果只靠肉眼观察,很难形成稳定结论。
循环赛制下的每场对局,又叠加了积分压力。选手状态、英雄/角色选择、地图策略都会相互影响。如果队伍里有队员状态波动,教练需要在赛后尽快给出量化反馈。没有数据支撑的复盘,很容易变成互相甩锅:打野怪中路不支援,辅助怪射手站位太靠前。而数据复盘可以让每个决策都有根据。
因此,这篇文章要解决的核心问题是:如何用一套低成本、可复用的数据工具链,把一场比赛的关键要素拆解成可对比、可追溯、可可视化的指标。具体来说,你会看到:
- 循环赛里的数据复盘为什么比淘汰赛更难做。
- 一场比赛要采集哪些最核心的数据维度。
- 用 Python 处理比赛日志、计算关键指标、绘制可视化图表的完整流程。
- 新手做比赛数据分析时经常踩的坑,以及对应的排查路径。
这不是一篇单纯介绍“电竞数据分析概念”的文章,而是从“清梦 VS Simon”这场景出发,带你跑通“数据采集 -> 数据清洗 -> 指标计算 -> 可视化 -> 结论输出”的完整闭环。
2. 循环赛与对局复盘的基本概念
2.1 循环赛为什么需要独立的数据视角
循环赛(Round-robin tournament)指的是每支参赛队伍都要与其他所有队伍各赛一场,最终以积分排名决定晋级名额。和淘汰赛相比,循环赛有更大的样本量,但也正因为要打很多场,单个小场的“偶然因素”会被放大。比如某支队伍在前期被一波团战打崩,这局输了,但在整个循环赛里,他们可能在另一场对局中展现出了更强的地图控制力。
所以分析循环赛时,不能只盯着单场输赢,而要看跨场次的稳定性指标。例如某选手的单局伤转率、分均经济、前15分钟补刀差等。而具体到“清梦 VS Simon”这一场,我们要做的是先建立一个标准复盘框架,再把这个框架应用到单局数据中。
2.2 复盘需要关注的核心数据维度
不同电竞项目的数据指标差异很大,但总体可以归类为五个维度:
| 维度 | 说明 | 常见指标 |
|---|---|---|
| 对线发育 | 衡量单线或全队前期资源获取能力 | 补刀数、分均经济、等级差、防御塔镀层 |
| 资源控制 | 衡量队伍对地图中立资源的掌控能力 | 小龙/大龙/远古资源、野区营地、视野得分 |
| 战斗效率 | 衡量团战和对抗的质量 | 击杀死亡助攻、参团率、伤害转化率 |
| 视野与信息 | 衡量地图信息控制能力 | 插眼数、排眼数、视野得分、控图率 |
| 阵容节奏 | 衡量阵容在时间轴上的强弱变化 | 阵容成型时间、前期强度、推塔速度 |
这些维度之间并不是独立的。比如视野控制差的队伍,往往更容易在小龙刷新时被对方抓到先手;发育曲线偏后期的队伍,前中期资源控制率通常偏低。复盘的难点在于找到“哪个指标先变化导致连锁反应”。
2.3 数据基础:时间序列和事件流
如果要进入代码层面,第一步是理解赛事数据的基本组织方式。绝大多数电竞比赛的数据不是一张静态表格,而是带有时间戳的事件流。
每场比赛通常包含:
- 对局元信息:比赛 ID、赛区、版本号、BP 信息、地图、开始时间。
- 事件列表:击杀事件、推塔事件、资源刷新/击杀事件、插眼/排眼事件、技能释放事件等。
- 时间序列数据:以分钟为单位的双方经济、经验、击杀数、视野分数等。
如果你手工记录一场比赛,也可以得到近似数据。但如果想自动化处理,就需要从官方接口或数据网站导出一个 JSON 或 CSV 文件。本文后面用到的示例数据,就是按这种结构组织的。
3. 环境准备与前置条件
做赛事数据分析不需要太高配置,但需要把 Python 环境准备好。以下环境以较通用版本为例,如果你的环境版本略有差异,不影响整体思路。
3.1 软件环境
- 操作系统:Windows 10/11、macOS、Linux 均可。
- Python:推荐 3.9 及以上版本。
- 包管理器:pip 或 conda。
3.2 Python 依赖库
我们需要用到以下库:
pandas:数据处理和表格计算。numpy:数值计算。matplotlib:基础可视化绘图。seaborn:高级统计图(可选,用于更美观的图表)。requests:请求数据接口(如果数据在远端)。
安装命令:
pip install pandas numpy matplotlib seaborn requests如果你的网络环境比较特殊,安装失败,可以使用国内镜像:
pip install pandas numpy matplotlib seaborn requests -i https://pypi.tuna.tsinghua.edu.cn/simple3.3 数据文件准备
在开始分析前,我们需要一份比赛数据。实际项目中有两种常见方式:
- 从官方赛事数据接口获取 JSON 数据。
- 从数据统计网站导出 CSV,或者手动整理表格。
为了这篇文章可以完整演示流程,我们会在本地创建一个模拟的比赛事件文件match_events.csv,并基于它做分析。你之后可以轻松替换成自己导出的真实数据。
4. 核心流程拆解
从零到一完成一场比赛的数据复盘,建议拆成五个步骤:
- 确定分析目标。
- 数据采集与导入。
- 数据清洗与字段加工。
- 指标计算与对比。
- 可视化与结论输出。
4.1 步骤一:确定分析目标
盲目跑数据是最常见的错误。分析“清梦 VS Simon”之前,先问自己一个问题:我是要分析“清梦为什么中期优势被翻盘”,还是“Simon 的视野布控如何压制对方”,还是“双方阵容在30分钟后的团战胜率差异”?
分析目标决定了你要重点看哪些数据。目标是“前期压制”,那就重点看 15 分钟前的经济差、补刀差、资源控制率。目标是“团战表现”,那就重点看参团率、伤害转化率、死亡贡献。
4.2 步骤二:数据采集与导入
接到官方 JSON 或 CSV 后,需要用 pandas 读取。如果是 JSON,先用json模块解析,再转成DataFrame。
4.3 步骤三:数据清洗与字段加工
真实数据会比示例脏很多。常见问题包括:
- 时间字段格式不统一。
- 击杀事件里的参与人员有缺失值。
- 同一个玩家在不同事件里 ID 大小写不一致。
- 经济曲线数据有重复行。
清洗时,我们统一做这几件事:
- 重命名列。
- 填充或删除缺失值。
- 统一时间戳单位为“分钟”。
- 将玩家 ID 归一化。
4.4 步骤四:指标计算与对比
这一步会根据你的目标,生成新的派生字段。
例如:
- 击杀参与率 = (选手击杀数 + 选手助攻数) / 全队总击杀数。
- 分均经济 = 总经济 / 比赛持续时间(分钟)。
- 经济差 = 己方经济 - 对方经济。
- 视野得分差 = 己方视野得分 - 对方视野得分。
- 伤害转化率 = 本队总伤害 / 本队总经济。
4.5 步骤五:可视化与结论输出
最后用图表辅助判断。常用的图包括经济曲线图、击杀事件散点图、选手能力雷达图、资源控制时间线等。
5. 完整示例代码实现
下面,我们用 Python 从零搭建一个小型赛事复盘工具。为了便于演示,先构造一份包含基本字段的比赛事件数据,然后执行完整的数据分析流程。
5.1 构造示例数据
先创建一个 CSV 文件match_events.csv。在实际项目中,这个文件应该由你的数据采集程序生成。
minute,event_type,team,player,detail 1,buy,blue,QingMeng,item_boots 2,ward_placed,blue,QingMeng,ward_pos_a 3,kill,blue,QingMeng,Simon_first_blood 4,ward_cleared,red,Simon,ward_pos_a_cleared 5,neutral_kill,blue,QingMeng,dragon 6,buildings_destroyed,blue,QingMeng,tower_top 7,kill,red,Simon,QingMeng_retreat 8,neutral_kill,red,Simon,herald 10,kill,blue,QingMeng,double_kill 12,buildings_destroyed,red,Simon,tower_mid 15,neutral_kill,blue,QingMeng,dragon 18,kill,red,Simon,team_fight_win 20,buildings_destroyed,blue,QingMeng,inhibitor 22,neutral_kill,blue,QingMeng,baron 25,kill,blue,QingMeng,ace 28,buildings_destroyed,blue,QingMeng,nexus这里我刻意构造了一个 28 分钟的比赛,蓝方“清梦”最终获胜。字段含义:
minute:比赛分钟。event_type:事件类型,如击杀、推塔、资源击杀、插眼、排眼。team:队伍标识,blue 表示清梦,red 表示 Simon。player:核心操作者。detail:事件详情。
这个数据虽然简单,但足以演示全流程。
5.2 读取数据并查看概览
写一个 Python 脚本analysis.py。
# 文件路径:analysis.py import pandas as pd df = pd.read_csv("match_events.csv") print("数据形状:", df.shape) print(df.head()) print(df.tail())运行方式:
python analysis.py预期输出(部分):
数据形状: (15, 5) minute event_type team player detail 0 1 buy blue QingMeng item_boots 1 2 ward_placed blue QingMeng ward_pos_a ...如果能看到列名和数据,说明读取成功。
5.3 数据清洗与字段加工
真实数据会有脏数据,所以我们演示清洗思路。
# 文件路径:analysis.py # 继续上面的脚本 # 1. 统一事件类型小写 df["event_type"] = df["event_type"].str.strip().str.lower() # 2. 把 player 中的空格去掉,防止大小写不一致 df["player"] = df["player"].str.replace(" ", "").str.title() # 3. 删除没有 player 的事件(比如某些全局事件) df = df.dropna(subset=["player"]) # 4. 按时间排序 df = df.sort_values("minute").reset_index(drop=True) print("清洗后数据:") print(df)在真实项目中,你还会处理缺失值和非法字符。这里用dropna处理缺失值,用str.title()统一人名大小写。
5.4 团队维度指标计算
现在计算双方的关键事件数量:
# 文件路径:analysis.py # 团队事件统计 team_stats = df.groupby("team")["event_type"].value_counts().unstack(fill_value=0) print("团队事件统计:") print(team_stats)输出类似:
event_type buildings_destroyed kill neutral_kill ward_cleared ward_placed team blue 2 4 3 0 1 red 2 2 1 1 0从事件计数可以初步判断双方打法:蓝方在中立资源上更主动,而红方视野清除做得更多。
5.5 选手维度指标计算
我们可以计算每个选手的击杀参与度。假设击杀事件中player字段记录的是完成最后一击的人,那么简单统计击杀数:
# 文件路径:analysis.py kill_df = df[df["event_type"] == "kill"] kill_counts = kill_df.groupby(["team", "player"]).size().reset_index(name="kill_count") print("击杀统计:") print(kill_counts)如果要算助攻和参与率,需要更详细的事件字段。这里仅演示统一接口。
5.6 计算经济时间序列并可视化
赛事数据里最有价值的图表之一,是双方经济随时间变化的曲线。虽然上面的事件数据里没有经济字段,我们可以模拟一个经济时间序列。实际项目中,economy_data.csv会包含minute、blue_economy、red_economy三列。
先生成模拟数据:
# 文件路径:analysis.py import numpy as np minutes = np.arange(0, 29, 1) blue_econ = 500 + 200 * minutes + np.cumsum(np.random.randint(50, 150, len(minutes))) red_econ = 500 + 180 * minutes + np.cumsum(np.random.randint(40, 160, len(minutes))) economy_df = pd.DataFrame({ "minute": minutes, "blue_economy": blue_econ, "red_economy": red_econ }) # 计算经济差:蓝方 - 红方 economy_df["economy_diff"] = economy_df["blue_economy"] - economy_df["red_economy"] print(economy_df.head())然后绘制经济曲线:
# 文件路径:analysis.py import matplotlib.pyplot as plt plt.rcParams["font.sans-serif"] = ["SimHei"] # Windows系统使用黑体,macOS可用Arial Unicode MS plt.rcParams["axes.unicode_minus"] = False fig, ax1 = plt.subplots(figsize=(10, 5)) ax1.plot(economy_df["minute"], economy_df["blue_economy"], label="清梦", color="blue") ax1.plot(economy_df["minute"], economy_df["red_economy"], label="Simon", color="red") ax1.set_xlabel("比赛分钟") ax1.set_ylabel("队伍经济") ax1.set_title("清梦 VS Simon 经济曲线") ax1.legend() ax1.grid(True, linestyle="--", alpha=0.6) ax2 = ax1.twinx() ax2.fill_between( economy_df["minute"], economy_df["economy_diff"], 0, where=economy_df["economy_diff"] >= 0, color="blue", alpha=0.15, label="蓝方经济领先" ) ax2.fill_between( economy_df["minute"], economy_df["economy_diff"], 0, where=economy_df["economy_diff"] < 0, color="red", alpha=0.15, label="红方经济领先" ) ax2.set_ylabel("经济差(蓝-红)") ax2.axhline(0, color="black", linestyle="--", linewidth=0.8) plt.tight_layout() plt.savefig("economy_curve.png", dpi=150) plt.show()如果脚本运行正常,你会看到一张双 Y 轴的经济曲线图。主 Y 轴显示双方的绝对经济,副 Y 轴显示经济差。图中蓝色区域表示清梦经济领先,红色区域表示 Simon 经济领先。
一眼就能看出比赛转折点:经济差从哪个时间段开始被拉开,或者被追近。
5.7 事件时间轴可视化
除了经济曲线,事件时间轴能帮我们定位关键节点。
# 文件路径:analysis.py fig, ax = plt.subplots(figsize=(12, 4)) teams = ["blue", "red"] colors = {"blue": "blue", "red": "red"} labels = {"blue": "清梦", "red": "Simon"} for team in teams: team_df = df[df["team"] == team] ax.scatter( team_df["minute"], [team]*len(team_df), color=colors[team], label=labels[team], s=80, edgecolor="white", zorder=3 ) ax.set_yticks([0, 1]) ax.set_yticklabels(["清梦", "Simon"]) ax.set_xlabel("比赛分钟") ax.set_title("清梦 VS Simon 关键事件时间轴") ax.legend() ax.grid(True, axis="x", linestyle="--", alpha=0.4) plt.tight_layout() plt.savefig("event_timeline.png", dpi=150) plt.show()这张图可以帮助你快速确认:哪一方在什么时间点完成了资源控制,哪一方被连续击杀导致节奏崩盘。
5.8 雷达图:选手六维能力评估
将选手表现抽象成六个维度:击杀、助攻、经济、输出、视野、推塔。先用模拟数据演示:
# 文件路径:analysis.py import numpy as np import matplotlib.pyplot as plt # 假设数值已经归一化到0~1 qingmeng_scores = { "击杀": 0.9, "助攻": 0.6, "发育": 0.8, "输出": 0.7, "视野": 0.5, "推塔": 0.8 } simon_scores = { "击杀": 0.7, "助攻": 0.8, "发育": 0.6, "输出": 0.8, "视野": 0.9, "推塔": 0.4 } labels = list(qingmeng_scores.keys()) num_vars = len(labels) angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist() angles += angles[:1] values_qm = [qingmeng_scores[label] for label in labels] values_qm += values_qm[:1] values_sm = [simon_scores[label] for label in labels] values_sm += values_sm[:1] fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True)) ax.plot(angles, values_qm, "o-", linewidth=2, color="blue", label="清梦") ax.fill(angles, values_qm, alpha=0.25, color="blue") ax.plot(angles, values_sm, "o-", linewidth=2, color="red", label="Simon") ax.fill(angles, values_sm, alpha=0.25, color="red") ax.set_xticks(angles[:-1]) ax.set_xticklabels(labels, fontsize=12) ax.set_ylim(0, 1) ax.set_title("选手能力六维雷达图") ax.legend(loc="upper right", bbox_to_anchor=(1.3, 1.0)) plt.tight_layout() plt.savefig("radar_chart.png", dpi=150) plt.show()雷达图非常适合做两名选手的横向对比。清梦在击杀、发育、推塔上占优,Simon 在助攻、输出、视野上占优。这能帮你客观判断谁更适合哪种战术定位。
5.9 生成分析报告
最后,我们把核心指标汇总并输出成一份简易报告。
# 文件路径:analysis.py summary = pd.DataFrame({ "team": ["清梦", "Simon"], "总击杀": [team_stats.loc["blue", "kill"], team_stats.loc["red", "kill"]], "推塔数": [team_stats.loc["blue", "buildings_destroyed"], team_stats.loc["red", "buildings_destroyed"]], "中立资源": [team_stats.loc["blue", "neutral_kill"], team_stats.loc["red", "neutral_kill"]], "视野事件": [ team_stats.loc["blue", "ward_placed"] + team_stats.loc["blue", "ward_cleared"], team_stats.loc["red", "ward_placed"] + team_stats.loc["red", "ward_cleared"] ] }) summary.to_csv("match_summary.csv", index=False, encoding="utf-8-sig") print("分析报告已生成:match_summary.csv")6. 运行结果与效果验证
6.1 运行完整脚本
把上面所有代码段合并到analysis.py中,然后运行:
python analysis.py正常执行后,你会看到如下输出:
- 清洗后的数据表。
- 团队事件统计。
- 击杀统计。
- 经济数据前 5 行。
- 提示“分析报告已生成:match_summary.csv”。
同时,当前目录下应该生成三个图片文件:
economy_curve.pngevent_timeline.pngradar_chart.png
以及一份 CSV 汇总报告match_summary.csv。
6.2 如何判断分析结果是否合理
不要只看图表漂不漂亮,要问三个问题:
- 数据是否和录像一致?比如录像里第 10 分钟清梦拿了双杀,那么
event_timeline.png的这个时间点应该有蓝色点。 - 指标是否会互相矛盾?如果一方经济一直领先但推塔数落后,说明对方可能在用后期阵容拖延时间,单看经济结论会误判。
- 图表能否讲出故事?一个好的复盘图,应该能让人一眼看到某个关键节点,然后顺着这个节点展开讨论。
如果发现图表异常,先回到原始数据检查时间戳、队伍字段是否对应,不要急着改可视化参数。
7. 常见问题与排查思路
在做“清梦 VS Simon”这类比赛数据复盘时,新手最容易遇到下面这些问题:
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| CSV 读取中文乱码 | 文件编码不是 UTF-8 | 用记事本另存为 UTF-8 | pd.read_csv("xxx.csv", encoding="utf-8")或encoding="gbk" |
| pandas 报 KeyError | 列名不匹配 | print(df.columns)查看实际列名 | 统一列名,或使用df.rename(columns={...}) |
| 图表中中文显示为方块 | 系统缺少对应中文字体 | print(plt.rcParams["font.sans-serif"])查看可用字体 | 设置plt.rcParams["font.sans-serif"] = ["SimHei"](Windows)或["Arial Unicode MS"](macOS) |
| 时间轴重叠看不清 | 事件过于密集 | 检查事件时间精度 | 用minute代替秒,或添加抖动(jitter) |
| 经济数据不连续 | 数据源有缺失分钟 | 检查时间列是否有空值 | df.groupby("minute").mean()重采样并补插值 |
| 统计总数和官方数据不一致 | 事件类型判断标准不同 | 对比官方计数规则 | 完善事件类型映射表 |
| 运行脚本提示 ModuleNotFoundError | 依赖库未安装 | pip list检查 | 执行pip install pandas matplotlib numpy |
8. 最佳实践与工程建议
8.1 数据命名与字段规范
无论是手工记录还是接口拉取,建议遵循统一的命名规范:
- 队伍统一使用
blue/red,避免出现“QingMeng”“QM”“qingmeng”多种写法。 - 时间统一为分钟小数,例如:
12.5表示 12 分 30 秒。 - 事件类型统一使用小写加下划线:
kill、ward_placed、neutral_kill、buildings_destroyed。 - 选手 ID 统一使用大写驼峰:
QingMeng、Simon。
好的命名规范能让你在后续做多场次对比时省下大量清洗时间。
8.2 分析脚本的模块化设计
不要把全部分析逻辑堆在一个文件里。建议拆成:
data/ raw/ # 原始数据 processed/ # 清洗后的数据 output/ # 图表和报告 scripts/ load_data.py # 数据加载 clean_data.py # 数据清洗 calculate.py # 指标计算 visualize.py # 可视化 build_report.py # 生成报告这样一个队或者一个选手的所有比赛,都能复用同一套代码。
8.3 多场比赛的横向对比
单场比赛的数据复盘往往容易以偏概全。比如某位选手在一场比赛中拿到了很多击杀,但如果你同时看他在循环赛前五场的伤害转化率,会发现他的击杀更多依赖队友补伤害。做循环赛分析时,建议把多场比赛数据聚合成一张面板表,然后做趋势分析:
- 分均经济随比赛轮次的变化。
- 视野得分在输赢场之间的差异。
- 前 15 分钟资源控制率与最终胜率的关系。
这样能发现选手或队伍的稳定性问题。
8.4 安全与合规注意事项
如果你要爬取外部赛事数据网站,务必注意以下几点:
- 只采集公开数据,不碰付费接口和登录后数据。
- 控制请求频率,避免给对方服务器带来压力。
- 遵守网站
robots.txt和用户协议。 - 如果官网提供官方 API,优先使用官方 API。
另外,将数据用于个人学习没问题,但如果要对外发布分析报告,建议做匿名化处理,避免涉及选手隐私和未公开的内部数据。
8.5 版本兼容与可复现性
Python 依赖库迭代很快,建议在项目目录下创建requirements.txt:
pandas==2.0.3 numpy==1.24.3 matplotlib==3.7.2 seaborn==0.12.2 requests==2.31.0运行时使用虚拟环境:
python -m venv venv source venv/bin/activate # Windows 下用 venv\Scripts\activate pip install -r requirements.txt这样你的分析代码在任何机器上都能复现相同结果。
8.6 复盘的最终输出要有人读
数据图只是中间产物,最终复盘一定要落到结论。建议每次分析结束时,输出一页文档,包含:
- 比赛基本信息。
- 一到两句话总结胜负关键。
- 三个关键数据点(比如“第15分钟经济差达到3000”“视野得分差为8”)。
- 两队下一场的改进建议。
不要把几十张图直接丢给教练,那样和没分析没有本质区别。
9. 总结与后续学习方向
这篇文章以“叶祁夏季赛循环赛清梦 VS Simon”为背景,完整演示了赛事数据分析的基础流程。从清洗比赛事件明细,到计算团队和选手指标,再到绘制经济曲线、事件时间轴和雷达图,你已经可以用 Python 独立完成一场比赛的技术复盘。
更值得关注的是,这套方法论并不仅限于这一场对局。换成其他队伍、其他赛区,甚至其他电竞项目,核心逻辑依然成立:先确定分析目标,再统一数据结构,然后用可复现的脚本计算关键指标,最后让图表帮助你把结论讲清楚。
如果你接下来想深入学习,建议从三个方向继续:
- 时间序列分析:用 pandas 的滚动窗口和重采样方法,分析经济和视野得分的动态变化。
- 选手表现预测模型:基于多场循环赛数据,用机器学习模型预测某位选手在下场比赛中是否可能成为关键先生。
- 自动复盘报告生成:把可视化结果和文字套话模板结合,使用
jinja2生成带图表的 Markdown 或 Word 报告。
最后给你一个简单但重要的建议:第一次做比赛数据复盘,不要一开始就追求复杂的模型。先把自己当作“数据整理员”,把一场比赛的数据老老实实清洗干净,画出一张能讲得清故事的经济曲线图,你就已经比大部分只看比分的人更接近比赛的本质了。
收藏这篇文章,下次看循环赛视频时,不妨同步打开数据分析脚本,你会发现原来“看比赛”和“读比赛”完全是两种体验。