在 LPL 这类职业电竞赛事结束后,数据网站上最常见的复盘配图之一就是“赛后数据雷达图”。类似“NIP 2-1 WBG 赛后数据雷达图”的标题,在比赛结束后的复盘文章、数据统计站点和社区讨论里出现频率很高。雷达图之所以被高频使用,是因为它能把 KDA、分均伤害、分均经济、视野得分、资源控制等不同维度的比赛数据压缩到一张图里,让读者快速看出两支队伍在哪些方面占优。这篇博客以 NIP 2-1 WBG 这场系列赛的场景为例,从数据理解、环境准备、数据整理、标准化、雷达图绘制到结果解读,完整走一遍“赛后数据雷达图”的制作流程。文中的数据为演示用示例数据,不是官方真实数据,重点在于把整套方法讲清楚,让读者可以拿任何一场比赛的数据直接套用。
1. 先理解赛后数据雷达图到底在表达什么
1.1 雷达图的本质:在同一个坐标系里比较多个维度的相对强弱
雷达图也叫蜘蛛网图、星形图,本质上是一个极坐标系下的折线图。每个指标占据一条从圆心向外延伸的轴,指标数值映射到轴的半径位置,把所有指标对应的点连接起来,就会形成一个闭合多边形。两支队伍的数据叠加在同一张图上,形状越饱满,代表这一维度数值越高;两条折线的面积差和方向差,代表了多维数据的整体差异。
如果只看单个指标,条形图或折线图比雷达图更精确。雷达图的价值在于同时呈现多个维度的“组合形态”。比如某支队伍 KDA 高、视野得分低,在雷达图上会形成“有一部分凸出、有一部分凹陷”的不规则形状;另一支队伍各维度都比较平均,则接近正多边形。这种形状差异比单纯看数字更有直觉冲击力,适合解说、图文复盘和短视频展示。
但也要注意一个关键限制:雷达图的面积和形状会受到指标排列顺序、指标数量、刻度范围影响。同样的数据,指标顺序打乱后,图形的“尖角”位置会变化,但相对关系不变。因此,做雷达图时最好固定指标顺序,避免每次输出形态不一致。
1.2 赛后数据雷达图适合放哪些指标
英雄联盟的赛后统计字段很多,但不能全部塞进雷达图。一个雷达图塞十多个指标,视觉上会变成密密麻麻的蜘蛛网,反而没有重点。常见做法是选取 5 到 7 个能反映队伍综合实力的核心指标。
下面是一组常用指标及说明:
| 指标 | 含义 | 常见单位 | 方向 | 说明 |
|---|---|---|---|---|
| KDA | 击杀、助攻综合与死亡的关系 | 比值 | 越高越好 | 常见计算为 (击杀 + 助攻) / 死亡,死亡为 0 时需要特殊处理 |
| DPM | 分均伤害 | 伤害值 / 分钟 | 越高越好 | 反映队伍团战和线上压制能力 |
| GPM | 分均经济 | 金币 / 分钟 | 越高越好 | 反映资源获取和发育效率 |
| CSPM | 分均补刀 | 补刀数 / 分钟 | 越高越好 | 反映线上基本功和边线处理能力 |
| VSPM | 分均视野得分 | 视野得分 / 分钟 | 越高越好 | 反映视野布控和排眼能力 |
| 资源控制率 | 大小龙、先锋等地图资源控制情况 | 百分比 | 越高越好 | 反映中立资源争夺能力 |
这些指标放在一起,基本可以覆盖“打架能力、发育能力、地图控制、视野博弈”四个维度。实际使用时,可以去掉“分均补刀”,因为分均经济已经部分包含补刀信息;也可以把“一血率”“推塔数”加进来,但指标总数尽量控制在 7 个以内。
需要注意一点:不是所有指标都是“越高越好”。比如场均死亡越低越好、场均用时越短越好。如果要把这类指标放进雷达图,必须做方向转换,例如使用“倒数”或“1 - 归一化值”,否则会误导看图的人。
1.3 为什么不能直接把原始数据画上去
先看一组模拟数据维度变化:
- KDA 通常在 2 到 6 之间。
- DPM 通常在 1500 到 3000 之间。
- VSPM 通常在 2 到 5 之间。
- 资源控制率是 0 到 1 之间的小数。
如果直接把原始数值作为半径画图,DPM 会在外圈,VSPM 会贴在内圈,整张图几乎只有一项指标可见,其他指标挤在圆心附近,完全失去比较意义。所以必须先做标准化,也就是把不同量纲的指标映射到同一个刻度范围。
常用的标准化方式有两种:
| 方式 | 计算方法 | 适用场景 | 缺点 |
|---|---|---|---|
| Min-Max 标准化 | (x - min) / (max - min) | 多个对象在同一批数据内比较 | 受极端值影响大 |
| 固定上限归一化 | x / 固定上限 | 长期统一对比 | 固定上限需要人为定义 |
| 最大值归一化 | x / 当前数据最大值 | 两队快速对比 | 容易掩盖单队绝对差距 |
对于单场比赛的两队雷达图,最简单的方式是取双方指标列的最大值作为分母,把数值缩放到 0 到 100,然后绘制在同一张图上。这种方式能突出“谁更强”,但会丢失“两队绝对水平都低”的信息。如果要做赛季长期对比,建议使用固定业务上限,比如 KDA 上限 10、DPM 上限 3000、GPM 上限 2000、CSPM 上限 10、VSPM 上限 5、资源控制率上限 1。上限明确后,雷达图能在多个比赛日之间保持一致的可比性。
注意:任何雷达图都要注明标准化方式。否则读者看到 80 分和 90 分,并不知道原始差距到底是 100 点伤害还是 1 点视野分。
2. 准备分析环境、数据和依赖
2.1 环境与依赖
这套流程使用 Python 实现,核心依赖是 pandas、numpy、matplotlib。如果希望生成网页端交互式雷达图,可以额外安装 pyecharts。下面是推荐环境:
| 依赖 | 用途 | 安装命令 |
|---|---|---|
| Python | 运行环境 | 建议 3.9 及以上版本 |
| pandas | 数据读取、清洗、标准化 | pip install pandas |
| numpy | 数值计算 | pip install numpy |
| matplotlib | 绘制静态雷达图 | pip install matplotlib |
| pyecharts | 绘制交互式 HTML 雷达图 | pip install pyecharts |
安装时没有强制锁定版本,但实际项目落地前,最好确认这几个包之间的兼容性。可以创建一个 requirements.txt 文件,固定自己验证过的版本,避免 pyecharts 升级后接口发生变化。
2.2 数据从哪里来
赛前赛后的比赛数据通常来自官方数据接口或第三方数据网站。个人做复盘时,可以从数据网站导出 CSV,也可以手动把每一局的击杀、助攻、死亡、补刀、分均伤害等字段录入表格。无论从哪里拿数据,都要遵守网站的数据使用规则,不要用高频率脚本抓取。
本文下面使用的是一份构造出来的示例数据,用来演示代码流程。数据结构尽量贴近常见赛后统计表,但数值不是具体某场比赛的真实数据。读者只要把 CSV 文件替换成自己要分析的比赛数据,代码逻辑可以基本不变。
2.3 准备一份结构化的示例数据
创建一个文件夹,例如lol_radar,在文件夹内准备match_data.csv。内容如下:
team,kda,dpm,gpm,cspm,vspm,objective NIP,4.20,2680.00,1850.00,8.40,3.60,0.78 WBG,3.10,2410.00,1775.00,7.90,3.10,0.55字段说明:
- team:队伍名。
- kda:队伍场均 KDA,越大越好。
- dpm:分均伤害,单位是数值/分钟。
- gpm:分均经济。
- cspm:分均补刀。
- vspm:分均视野得分。
- objective:大小龙资源控制率,0 到 1 之间。
由于这是一份只有两行的数据,pandas 读取后会非常简单,但足够说明雷达图的全流程。实际分析中,如果展开到单局数据,可以按“队伍 + 局数”拆分后分别绘制。
import pandas as pd df = pd.read_csv("match_data.csv") print(df.head()) print(df.info())读取后打印的df.info()会显示各列类型,便于检查是否存在缺失值。
3. 用 pandas 完成清洗和标准化
3.1 读取数据并检查字段
读取之后,第一件事不是画图,而是确认数据的列名、类型和范围。可以执行:
print(df.columns.tolist()) print(df.dtypes)正常输出应该包含 7 列,数值列类型为 float64 或 int64。如果某列出现了 object 类型,说明文件里有非数值内容,需要定位到具体行检查。
3.2 缺失值和异常值处理
赛程数据里偶尔会出现缺失字段。常见处理方式如下:
| 场景 | 处理方式 |
|---|---|
| 某个指标缺失 | 如果该项是队伍明显没有产生数据,可填 0;如果是数据采集遗漏,可用前后场均值填充 |
| KDA 死亡数为 0 | 常见统计中会记作 Perfect KDA,或使用 (击杀 + 助攻) / 最大(死亡, 1) |
| 资源控制率大于 1 | 数据不合法,需要回到原始记录核对 |
| 分均伤害为负数 | 数据不合法,删除或修正 |
对于本文的示例数据,没有缺失值,但写代码时还是要养成检查习惯:
print(df.isna().sum())如果存在缺失值,最简单的做法是使用fillna(0)或对当前列进行数值填充。
3.3 标准化并转换为百分制
下面定义需要参与雷达图绘制的指标列顺序,这一步非常重要。雷达图绘制时会把列顺序作为轴顺序,顺序不一致会导致标签和折线错位。
score_cols = ["kda", "dpm", "gpm", "cspm", "vspm", "objective"]选择不同的标准化基准会直接影响雷达图形状。这里先实现“当前数据最大值归一化到 100 分”的版本,适合快速比较两支队伍:
import numpy as np def normalize_to_max(df, cols): normalized = df.copy() for col in cols: max_val = normalized[col].max() if max_val == 0: normalized[col + "_score"] = 0 else: normalized[col + "_score"] = normalized[col] / max_val * 100 return normalized df_score = normalize_to_max(df, score_cols) print(df_score)输出结果中每支队伍会多出kda_score、dpm_score等字段,数值范围在 0 到 100 之间。由于每列的最大值来自两支队伍中较大的一方,因此每列至少有一支队伍是 100 分。
如果希望按固定业务上限标准化,可以使用:
upper_bounds = { "kda": 10, "dpm": 3000, "gpm": 2000, "cspm": 10, "vspm": 5, "objective": 1, } def normalize_with_bounds(df, cols, bounds): normalized = df.copy() for col in cols: bound = bounds[col] normalized[col + "_score"] = normalized[col] / bound * 100 return normalized df_bound = normalize_with_bounds(df, score_cols, upper_bounds) print(df_bound)固定上限方式的优点是不同比赛、不同日期的图表可以纵向比较;缺点是如果上限设置过高,所有队伍分数都会偏低,视觉上差别不明显。两种方式都可以用,关键是绘图前明确“这张图的 100 分代表什么”。
注意:如果采用最小值最大值归一化,只有两支队伍时,最大值队是 100 分,最小值队是 0 分。0 分会让雷达图的某条边缩到圆心,看起来像“缺了一个角”,这在少数指标上确实能说明问题,但也会让图形比例过度夸张。使用固定上限或最大值归一化,能避免评分项变成 0。
3.4 整理绘制雷达图所需的数据结构
绘制雷达图时,最好准备一个只包含队伍名和百分制得分的表:
plot_df = df_score[["team"] + [col + "_score" for col in score_cols]].copy() print(plot_df)此时plot_df的行是队伍,列是评分。后面绘图函数可以基于这个表直接读取。
4. 用 matplotlib 绘制可复用的雷达图
4.1 最简绘制代码
使用 matplotlib 绘制雷达图时,常用projection="polar"创建极坐标轴。下面这段代码是基础版本:
import matplotlib.pyplot as plt import numpy as np # 中文字体设置 plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False metrics = [col + "_score" for col in score_cols] num_vars = len(metrics) # 角度计算:把圆等分成 num_vars 份 angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist() # 闭合图形:首尾相连 angles += angles[:1] fig, ax = plt.subplots(figsize=(8, 8), subplot_kw={"projection": "polar"}) ax.set_theta_offset(np.pi / 2) ax.set_theta_direction(1) for row in plot_df.itertuples(index=False): team_name = row[0] values = list(row[1:]) values += values[:1] ax.plot(angles, values, label=team_name, linewidth=2) ax.fill(angles, values, alpha=0.15) ax.set_xticks(angles[:-1]) ax.set_xticklabels([col.replace("_score", "").upper() for col in metrics]) ax.set_ylim(0, 100) ax.legend(loc="upper right", bbox_to_anchor=(1.2, 1.0)) plt.title("NIP vs WBG 赛后数据雷达图") plt.show()代码的关键点有三个:
endpoint=False保证第一个指标不在最后一个点重复,否则角度会把圆分成不均匀的段。angles += angles[:1]和values += values[:1]是为了闭合折线,让最后一条边回到起点。set_theta_offset(np.pi / 2)让第一根轴朝向正上方,set_theta_direction(1)让角度按顺时针排列,更符合常见雷达图的阅读习惯。
4.2 双队对比与样式优化
双队对比时,两个多边形可能重叠,为了区分,可以给每支队伍指定不同颜色、线型和透明度:
colors = {"NIP": "#d62728", "WBG": "#1f77b4"} fig, ax = plt.subplots(figsize=(8, 8), subplot_kw={"projection": "polar"}) ax.set_theta_offset(np.pi / 2) ax.set_theta_direction(1) for row in plot_df.itertuples(index=False): team_name = row[0] values = list(row[1:]) values += values[:1] ax.plot(angles, values, label=team_name, linewidth=2.5, color=colors[team_name]) ax.fill(angles, values, alpha=0.12, color=colors[team_name]) ax.set_xticks(angles[:-1]) ax.set_xticklabels([col.replace("_score", "").upper() for col in metrics], fontsize=12) ax.set_ylim(0, 100) ax.grid(linestyle="--", linewidth=0.6) ax.legend(loc="upper right", bbox_to_anchor=(1.2, 1.0)) plt.title("NIP vs WBG 赛后数据雷达图", fontsize=15) plt.tight_layout() plt.show()颜色选择上,尽量选色差明显的两个颜色,避免红绿色盲无法区分。填充透明度不要太高,否则重叠区域会变成深色块,反而看不清两条折线边界。
4.3 保存图片
保存图片时注意分辨率和边距:
fig.savefig("nip_vs_wbg_radar.png", dpi=300, bbox_inches="tight")dpi=300适合发布到网页或PPT,清晰度足够。bbox_inches="tight"会裁掉多余白边,让图片更紧凑。
如果图片要放在深色背景的页面里,可以增加facecolor="white"参数,避免 PNG 背景透明导致文字和图形混在一起。
5. 用 pyecharts 生成交互式雷达图
5.1 为什么需要交互版本
matplotlib 输出的静态 PNG 适合直接嵌入到图文里,但交互性不足。如果希望读者在网页上悬停查看具体数值,或者切换显示某一支队伍,可以使用 pyecharts 生成 HTML 文件。pyecharts 底层封装了 ECharts,渲染效果好,适合数据复盘站、日报页面和实时展示场景。
5.2 pyecharts 实现示例
pyecharts 的 Radar 组件需要先声明indicator,也就是每个指标的名称和最大值。由于我们已经在前面把数据转成百分制,这里可以把最大值统一设置为 100。
from pyecharts import options as opts from pyecharts.charts import Radar indicator = [ {"name": "KDA", "max": 100}, {"name": "DPM", "max": 100}, {"name": "GPM", "max": 100}, {"name": "CSPM", "max": 100}, {"name": "VSPM", "max": 100}, {"name": "OBJECTIVE", "max": 100}, ] data = [] for row in plot_df.itertuples(index=False): team_name = row[0] values = list(row[1:]) data.append((team_name, values)) c = Radar() c.add_schema(schema=indicator) for team_name, values in data: c.add( series_name=team_name, data=[values], linestyle_opts=opts.LineStyleOpts(width=2), areastyle_opts=opts.AreaStyleOpts(opacity=0.1), ) c.set_global_opts( title_opts=opts.TitleOpts(title="NIP vs WBG 赛后数据雷达图"), legend_opts=opts.LegendOpts(), ) c.render("nip_vs_wbg_radar.html")运行后会生成一个nip_vs_wbg_radar.html文件,浏览器打开即可交互。需要注意 pyecharts 1.x 和 2.x 的 API 有差异,上面写法以常见的 1.x 版本为基础。如果安装的是较新版本,最好参考当前版本的官方示例调整参数。
5.3 两种工具对比
| 对比项 | matplotlib | pyecharts |
|---|---|---|
| 输出形式 | PNG、JPG、SVG | HTML、Web 组件 |
| 交互能力 | 弱 | 强,支持悬停、图例切换 |
| 中文字体 | 需要手动配置 | 浏览器自动处理 |
| 适合场景 | 公众号、图文、PPT | 网页、数据平台、实时看板 |
| 学习成本 | 较低 | 中等,需要了解 ECharts 概念 |
| 批量生成 | 方便 | 同样方便,但文件大一些 |
实际生产项目中,建议两者结合:一批图用 matplotlib 生成静态图片用于汇报,另一批用 pyecharts 生成 HTML 用于网页端投放。
6. 读懂雷达图:从形状差异到比赛内容
6.1 先看整体面积,再看单项突出
雷达图的第一眼信息是“两块多边形谁的面积更大”。在示例数据中,NIP 在 KDA、DPM、GPM、CSPM、VSPM、OBJECTIVE 六个维度上都比 WBG 高,所以 NIP 的多边形会明显更饱满,这对应了系列赛 2-1 的胜负关系。
但面积本身不是绝对结论。雷达图的每个轴权重相同,而实际比赛中视野、资源控制等维度的重要性并不是等价的。因此,读图时要先判断哪些指标主导了比赛,再回到比赛录像或逐局数据里验证。
6.2 找差异最大的维度作为切入点
差异最大的维度是复盘时最值得展开的切入点。假设示例数据中两队资源控制率差异很大,那么可以优先回看大小龙时间点:
- 是先锋团、小龙团的阵容优势导致的必然结果?
- 是打野在关键时间点提前落位,形成了视野和位置差?
- 还是某一波团战中抢龙导致的偶然结果?
这些判断无法从一张雷达图直接得出,但雷达图能快速提示“应该优先看哪个环节”。KDA 的差异则可以结合击杀时间线,判断是前期对线打出优势,还是中后期团战才拉开差距。
6.3 警惕“数据因果化”误区
雷达图是统计结果,不是因果证据。它不能反映下面这些信息:
- 阵容前中后期曲线,比如某队拿到后期阵容,前期经济落后但中后期翻盘。
- 单局波动,比如第一局碾压、第二局被碾压、第三局险胜,汇总后可能“看起来差距不大”。
- 选手或队伍的失误操作、大小龙被抢、关键技能空掉等细节。
- BP 阶段的针对性选择,比如为限制对手中路而牺牲了部分前期对线能力。
因此,做赛后复盘时,建议把雷达图作为“索引”,而不是最终结论。先看雷达图找差异维度,再看分均经济和击杀时间线,最后回到比赛录像确认产生差异的具体回合。
6.4 可以搭配哪些图一起使用
只放一张雷达图,信息量有限。推荐搭配以下图表:
| 图表 | 说明 |
|---|---|
| 经济曲线折线图 | 看单局节奏和翻盘点 |
| 单局伤害对比柱状图 | 看选手输出分布 |
| 视野得分时间序列图 | 看视野布控节奏变化 |
| 资源控制事件表 | 看大小龙、先锋刷新和归属时间点 |
这样组合后,雷达图承担“概览”职责,其他图表承担“细节证据”职责,复盘内容会更扎实。
7. 常见坑与排查路径
7.1 中文标签变成方块
现象:雷达图指标名称出现“□□”或乱码。
原因:matplotlib 默认字体不支持中文。
检查方式:查看当前环境可用字体,或直接打印plt.rcParams["font.sans-serif"]。
解决方式:
plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False如果系统没有 SimHei,可以指定其他中文字体路径:
from matplotlib import font_manager font_manager.fontManager.addfont("path/to/font.ttf") plt.rcParams["font.family"] = "YourFontName"7.2 雷达图没有闭合成环
现象:折线从第一个点画到最后一个点就结束,图形是开口的。
原因:没有把第一个点的数值复制到序列末尾。
解决方式:绘图前对 values 和 angles 都追加第一个元素:
values += values[:1] angles += angles[:1]7.3 标准化后出现 0 分,图形塌陷
现象:某个指标贴着圆心,看起来像“少了半边”。
原因:如果使用 Min-Max 标准化,两支队中数值最小的队伍会得到 0 分。
解决方式:改用固定上限归一化,或对 0 分做下限保护,比如限制最低得分为 5 分。这样图形不会完全贴地,视觉上也更容易保留潜在信息。
7.4 多队折线重叠,无法区分
现象:三支以上队伍画在一张雷达图里,颜色接近,看不出谁是谁。
解决方式:
- 使用明显色差。
- 使用不同线型,如实线、虚线、点划线。
- 给折线增加标记点,如圆形、方形。
- 降低填充透明度,保留主要折线。
如果队伍超过 4 支,建议拆分成多个雷达图单独展示,或改用平行坐标图。
7.5 pyecharts 版本不同导致 API 不生效
现象:add_schema不存在,或Radar初始化报错。
原因:pyecharts 1.x 和 2.x 的接口差异较大。
检查方式:运行pip show pyecharts查看版本。
解决方式:按版本查找官方示例。建议在 requirements.txt 中固定一个验证过的版本,避免后续升级破坏脚本。
| 问题现象 | 常见原因 | 检查方式 | 处理建议 |
|---|---|---|---|
| 中文乱码 | 字体缺少中文字符 | 检查 matplotlib 字体配置 | 设置中文字体或指定字体路径 |
| 图形不闭合 | 首尾点未拼接 | 检查 values 长度是否比 angles 少 1 | 绘图前追加第一个点 |
| 指标错位 | 列顺序和标签顺序不一致 | 打印 score_cols 和 xticklabels | 固定指标列表,按同一顺序传入 |
| 数值超出网格 | 未设置 ylim | 检查数据最大值 | set_ylim(0, 100) |
| HTML 文件无法打开 | 渲染路径错误 | 检查 render 输出路径 | 使用绝对路径或确认当前目录 |
8. 最佳实践与扩展方向
8.1 把可复用函数写出来
手动复制绘图代码很容易出错。推荐封装成一个函数:
def draw_radar(plot_df, metrics, title="Radar", output_path="radar.png"): num_vars = len(metrics) angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist() angles += angles[:1] fig, ax = plt.subplots(figsize=(8, 8), subplot_kw={"projection": "polar"}) ax.set_theta_offset(np.pi / 2) ax.set_theta_direction(1) for row in plot_df.itertuples(index=False): team_name = row[0] values = list(row[1:]) values += values[:1] ax.plot(angles, values, label=team_name, linewidth=2) ax.fill(angles, values, alpha=0.12) ax.set_xticks(angles[:-1]) ax.set_xticklabels(metrics) ax.set_ylim(0, 100) ax.legend(loc="upper right", bbox_to_anchor=(1.2, 1.0)) ax.set_title(title) fig.savefig(output_path, dpi=300, bbox_inches="tight") return output_path使用这个函数时,plot_df必须已经包含“队伍名列 + 百分制评分列”,并且评分列的顺序与metrics一致。这样每次赛后只需要替换 CSV 文件,调用一次函数就能生成新的雷达图。
8.2 自动化复盘怎么落地
如果要持续产出赛后雷达图,可以将流程脚本化:
- 从数据源导出 CSV,或通过合规接口定时拉取。
- 脚本执行数据清洗、标准化、绘图。
- 生成 PNG 和 HTML 文件,输出到固定目录。
- 由前端页面或文档系统引用生成的图片。
自动化流程中必须注意:
- 每次运行前确认数据文件是否完整,避免空文件导致脚本报错。
- 保留原始 CSV 和历史版本图片,方便回溯对比。
- 日志要记录标准化基准和生成时间,防止不同比赛的图被混在一起比较。
- 如果脚本部署在服务器上,需要控制文件访问权限,避免他人任意修改数据文件。
8.3 扩展方向
雷达图只是比赛数据可视化的起点。后续可以扩展的方向包括:
| 方向 | 说明 |
|---|---|
| 逐局雷达图 | 把每一局比赛单独生成雷达图,观察队伍状态波动 |
| 选手个人雷达图 | 将选手的分均伤害、参团率、承伤占比等指标单独绘制 |
| 赛季分位基准 | 使用赛季所有比赛数据计算中位数、分位数,形成统一基准 |
| 动态时间轴 | 用时间轴展示经济差、经验差的演变,配合雷达图整体观感 |
| 前端图表组件 | 使用 ECharts 的 Radar 组件接入数据平台,实现点选交互 |
对新手来说,最有价值的练习是:找一场自己已经看过完整回放的比赛,按照本文流程手动整理数据,生成雷达图后,看自己能不能从雷达图上找到与比赛记忆一致的信息。如果雷达图显示某个指标异常突出,但实际比赛里并没有对应记忆,通常说明数据整理或标准化方式有问题。这种“用比赛记忆验证图表”的练习,比单纯抄代码更有利于建立数据感觉。
8.4 生产发布前检查清单
发布赛后数据雷达图前,建议按下面清单检查一遍:
- [ ] 数据来源是否可信,是否标注了“示例数据”或官方数据。
- [ ] 指标列顺序是否固定,标签与数据是否一一对应。
- [ ] 是否说明了标准化方式,比如“按本场比赛最大值归一化为 100”。
- [ ] 中文标签是否正常显示,导出图片是否有乱码。
- [ ] 图片分辨率足够,是否用 300 dpi 导出。
- [ ] 是否补充了比赛进程信息,避免读者误把雷达图差异当作直接获胜原因。
- [ ] 如果是自动化脚本,是否记录了数据文件路径、生成时间和版本。
雷达图的价值不在“画得多好看”,而在于能否把多维数据压缩成可读的形状差异,并引导读者回到比赛细节中去验证。把绘制流程固定成脚本之后,每周赛后只需要更新 CSV,就能在几分钟内产出一张规范的赛后数据雷达图。这套流程同样可以迁移到选手数据、赛季积分、战队历史状态对比等场景。