Python在同一张图中绘制多系列对比雷达图

小鹿同学
小鹿同学
发布时间:2026-10-27 | 4人浏览过
原创

本文系统讲解如何使用Python与Matplotlib在同一张极坐标图中绘制多系列对比雷达图。涵盖等分角度计算、数据首尾闭合机制、多系列循环绘图、透明度设置与极轴方向调整的完整实战指南。

在同一张图表内绘制多系列对比雷达图(Radar Chart),核心在于借助 Matplotlib 的极坐标投影模式(projection='polar'),将多个维度的指标映射到圆周角度上,并通过数据首尾拼接保证多边形完全闭合,最后按系列循环绘制不同色彩的线条与半透明填充层。掌握极坐标网格、等分角度计算以及重叠层级优化,就能在一张图中清晰对比多个对象在各项性能指标上的综合表现。

Python在同一张图中绘制多系列对比雷达图
图1:Python极坐标绘制多系列对比雷达图的核心流程

一、极坐标绘图原理与“首尾闭合”机制

很多初学者在第一次尝试使用 Matplotlib 绘制雷达图时,常会遇到多边形“少了一条边”或者填充颜色出现怪异切角的问题。要解决这个问题,必须先理解雷达图的几何本质。

雷达图本质上是极坐标系下的折线图与填充多边形。在二维平面直角坐标系中,点由 (x, y) 确定;而在极坐标系中,点由角度 $\theta$(弧度)与极径 $r$(数值大小)确定。若有 $N$ 个评估维度,我们需要把一整个圆周($2\pi$ 弧度)均匀切分为 $N$ 个等分角:

angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()

这里的关键参数是 endpoint=False。若设为 True,生成的 $N$ 个角就会把最后一个角分配在 $2\pi$ 处,从而与 0 弧度重合,导致中间维度的夹角缩水。因此必须排除终点,得到 $N$ 个互不重合的等分角度。

而在执行折线连接时,Matplotlib 只是依序将相邻点连成线段,它并不知道最后一个点需要连回第一个点。为了让线条环绕成一个封闭的环形多边形,必须手动将数组的第一个元素复制并追加到末尾:

# 闭合角度数组与数值数组
angles_closed = angles + angles[:1]
values_closed = values + values[:1]

只有当角度数组与数值数组都完成首尾拼接后,ax.plot() 与 ax.fill() 才能渲染出完全封闭的多边形轮廓。

Python在同一张图中绘制多系列对比雷达图
图2:数据闭合与否对雷达图几何形状及面积渲染的直接影响

二、完整可执行代码示例

下面是一个完整可运行的示例。我们在同一张画布中对比三款不同定位的电子产品(旗舰机型、轻薄便携机型与性价比机型),展示其在六大维度上的综合表现。

import numpy as np
import matplotlib.pyplot as plt

# 解决中文显示与负号问题
plt.rcParams['font.sans-serif'] = ['PingFang SC', 'Microsoft YaHei', 'SimHei', 'sans-serif']
plt.rcParams['axes.unicode_minus'] = False

# 1. 定义对比维度与各个系列的数据
categories = ['计算性能', '电池续航', '便携轻量', '屏幕素质', '散热控制', '制造质感']
num_vars = len(categories)

data_series = {
    '旗舰机型 A': [95, 80, 72, 98, 88, 92],
    '轻薄机型 B': [78, 92, 96, 85, 70, 84],
    '性价比机型 C': [86, 85, 78, 76, 82, 75]
}

# 2. 计算每个维度的等分角度并完成闭合
angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()
angles += angles[:1]  # 追加首项角度

# 3. 创建极坐标画布
fig, ax = plt.subplots(figsize=(7, 7), subplot_kw=dict(polar=True))

# 调整起始角度为正上方(12点钟位置),方向设为顺时针
ax.set_theta_offset(np.pi / 2)
ax.set_theta_direction(-1)

# 设置外围维度的文字标签
plt.xticks(angles[:-1], categories, color='#334155', size=11)

# 设置径向刻度线与范围(0~100分)
ax.set_rlabel_position(0)
plt.yticks([20, 40, 60, 80, 100], ['20', '40', '60', '80', '100'], color='#94a3b8', size=9)
plt.ylim(0, 100)

# 4. 循环绘制每个系列
# 定义系列色彩与数据点标记符号
styles = [
    {'color': '#52677D', 'marker': 'o', 'linestyle': '-'},
    {'color': '#A66C5B', 'marker': 's', 'linestyle': '-'},
    {'color': '#4A7C59', 'marker': '^', 'linestyle': '-'}
]

for (name, values), style in zip(data_series.items(), styles):
    values_closed = values + values[:1]  # 数值追加首项闭合
    # 绘制折线与端点标记
    ax.plot(
        angles, values_closed,
        label=name,
        color=style['color'],
        marker=style['marker'],
        markersize=6,
        linewidth=2,
        linestyle=style['linestyle']
    )
    # 半透明填充多边形区域
    ax.fill(angles, values_closed, color=style['color'], alpha=0.18)

# 5. 图例与排版美化
plt.title('三大机型核心维度综合评测对比', size=14, color='#0f172a', weight='bold', pad=25)
plt.legend(loc='upper right', bbox_to_anchor=(1.25, 1.1), frameon=True, facecolor='#ffffff')
plt.tight_layout()
plt.show()

代码细节提醒:plt.xticks() 绑定的角度必须是切片 angles[:-1],因为原始的 categories 只有 6 个元素。如果传入已经闭合的 7 个角度,Matplotlib 会报出“标签数量与刻度数量不一致”的长度不匹配错误。

Python在同一张图中绘制多系列对比雷达图
图3:多系列对比雷达图自底向上的视觉渲染层级关系

三、多系列对比的关键视觉调优技巧

单系列雷达图往往只要形状正确即可,但多系列雷达图存在严重的多边形互相重叠遮挡问题。如果配置不当,图表极容易变成一团混杂的色块。为了确保信息易读,建议落实以下几项具体调整:

1. 控制系列数量与色彩对比

在同一张雷达图中,推荐对比的系列数量为 2 至 4 个。超过 4 个系列时,多边形交织会显著增加读者的认知负担。如果必须对比更多对象,应考虑拆分为多个子图或采用柱状图平行对比。色彩上推荐选用主色调配合辅助对比色,如主色蓝灰 #52677D、赭红 #A66C5B 与橄榄绿 #4A7C59,避免使用亮度过高、刺眼的饱和原色。

2. 差异化填充透明度与线型标记

多边形重叠时,填充颜色的不透明度至关重要。若 alpha 值过高(如大于 0.5),上层的色块会完全掩盖底层的图形;若完全不填充,仅凭细线又难以直观感受整体“体量感”。将 alpha 控制在 0.15 到 0.25 之间最为适宜。此外,为不同系列指定不同的端点标记(如 marker='o'、marker='s'、marker='^')或线型(虚线与实线搭配),即使在黑白打印或色弱读者的屏幕上,也能清晰区分每个系列。

3. 起始角度偏移与顺时针布局

Matplotlib 的极坐标默认从极径正右侧(即时钟 3 点钟方向,0 弧度)开始,且以逆时针方向旋转排布。这种排布方式与大多数人阅读仪表盘的直觉(习惯从 12 点钟位置开始、顺时针阅读)相反。通过以下两行代码可以校正:

ax.set_theta_offset(np.pi / 2)  # 将起点旋转90度至12点钟正上方
ax.set_theta_direction(-1)      # 设置为顺时针方向递增

4. 统一量纲与显式固定极径范围

绘制对比图时,必须显式调用 plt.ylim(min_val, max_val) 锁定极径上下界。如果不显式限制,Matplotlib 会根据当前系列输入数据的极小值与极大值自动调整网格中心与外圈。这会导致不同子图之间失去可比性,甚至让中心点数值不为零,造成图形比例的严重失真。

Python在同一张图中绘制多系列对比雷达图
图4:绘制多系列雷达图时的核心检查要点与避坑指导

四、常见问题排查

  • 外围文字标签与图表重叠挤压:当维度名称较长时,标签可能会压在最外层网格线上。可以通过微调字体大小 size=10,或者利用 ax.tick_params(pad=12) 增大标签与圆环的距离来解决。
  • 多个维度的单位与量级差异极大:例如“跑分”是数十万分,而“续航”是小时数(个位数)。如果直接绘制,小数值维度会被压缩到圆心完全看不清。此时必须先做 Min-Max 归一化,将每个维度的指标统一映射至 0~100 的无量纲分值区间内再行绘图。
  • 导出图片时图例被裁切:由于使用了 bbox_to_anchor=(1.25, 1.1) 将图例挪到了画布外部,在调用 plt.savefig('radar.png') 时需加上参数 bbox_inches='tight',防止图例超出默认保存视口而被截断。
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表