Matplotlib 雷达图函数
雷达图,也叫做 “极坐标图” 或 “蜘蛛网图”,它是一种用于表现多维(4 维以上)数据的图表(如下图)。对于雷达图来说,它起始于同一个圆心点,结束于最外围边缘。其中,每个坐标点代表一个指标。

在 Matplotlib 中,我们可以使用 polar() 函数来绘制一个雷达图。
语法:
plt.polar(theta, r)说明:
第 1 个参数 theta 表示数据点所在射线与极轴的夹角。需要注意的是,所有的角度都应该使用 “弧度” 为单位,例如 180° 就应该写成 np.pi,而 360° 就应该写成 np.pi * 2,以此类推。
在实际开发中,我们更推荐使用这种写法:度数 * np.pi / 180。这种写法可以让我们一眼就能看出角度是多少,例如下面这 2 个。
120 * np.pi / 180 # 120°
150 * np.pi / 180 # 150°第 2 个参数 r 是数据点到原点的距离,一般它对应实际的数据。
示例 1:画出一个点
import numpy as np
import matplotlib.pyplot as plt
# 绘图
plt.polar(45*np.pi/180, 40, marker='o', color='red')
# 刻度范围
plt.ylim(0, 100)
# 显示
plt.show()运行之后,效果如下图所示。

分析:
想要绘制一个雷达图,我们首先要学会如何在一个极坐标中绘制一个点出来。在这个例子中,plt.polar(45*np.pi/180, 40, marker='o', color='red') 表示绘制的点所处夹角为 45°,距离原点为 20,外观是一个实心圆,颜色为红色。
对于雷达图来说,我们一般都不会使用默认刻度,而需要使用 ylim() 函数来调整刻度范围。如果使用默认刻度,比如删除 plt.ylim(0, 100) 这一句代码,效果如下图所示,此时效果就不是很理想了。

示例 2:画出雷达图
import numpy as np
import matplotlib.pyplot as plt
# 绘图
theta = np.array([45, 135, 180, 270, 45]) * np.pi / 180
r = [20, 60, 40, 80, 20]
plt.polar(theta, r, marker='o', color='red')
# 刻度范围
plt.ylim(0, 100)
# 显示
plt.show()运行之后,效果如下图所示。

分析:
想要绘制一个雷达图,我们需要确定多个点的坐标,然后将所有点连接起来。由于雷达图是一个封闭图形,它的第一个点和最后一个点要求是相同的。所以 这里可以看到 theta 的第一个元素和最后一个元素是相同的,并且 r 的第一个元素和最后一个元素是相同的。
需要注意的是,np.pi 是一个浮点数,而列表是无法和一个浮点数进行相乘的。所以我们应该先使用 np.array()(这是一个 NumPy 函数)将列表转换为数组,然后再和浮点数进行相乘。
# 正确方式
theta = np.array([45, 135, 180, 270, 45]) * np.pi / 180
# 错误方式
theta = [45, 135, 180, 270, 45] * np.pi / 180此外需要说明的是,雷达图中每一个点的坐标是由 “角度” 和 “距离” 这两个来确定的。小伙伴们联想一下极坐标系中一个点是如何确定的就知道了。
Matplotlib 雷达图样式
在实际开发中,为了达到更好的用户体验,我们还需要对雷达图进行各种自定义,主要包括 2 个方面:① 刻度标签;② 填充颜色。
1. 刻度标签
有些情况下,雷达图默认的刻度标签并不能满足我们的开发需求。在 Matplotlib 中,我们可以使用 thetagrids() 函数来定义雷达图的刻度标签。
语法:
plt.thetagrids(angles, labels)说明:
angles 和 labels 都是列表。ticks 是必选参数,表示 “刻度所在的角度”。labels 是可选参数,表示 “标签值”。其中 labels 是与 angles 一一对应的。
示例 3:雷达图刻度标签
import numpy as np
import matplotlib.pyplot as plt
# 绘图
plt.polar(60*np.pi/180, 40, marker='o', color='red')
# 刻度范围
plt.ylim(0, 100)
# 刻度标签
angles = [0, 60, 120, 180, 240, 300]
plt.thetagrids(angles)
# 显示
plt.show()运行之后,效果如下图所示。

分析:
默认情况下,雷达图的刻度标签为:0°、45°、90°、135°、180°、225°、270°、315°。在这个例子中,我们将其刻度标签重新定义为:0°、60°、120°、180°、240°、300°。
示例 4:定义 labels
import numpy as np
import matplotlib.pyplot as plt
# 设置
plt.rcParams['font.family'] = ['SimHei', 'PingFang SC']
plt.rcParams['axes.unicode_minus'] = False
# 绘图
plt.polar(60*np.pi/180, 40, marker='o', color='red')
# 刻度范围
plt.ylim(0, 100)
# 刻度标签
angles = [0, 60, 120, 180, 240, 300]
labels = ['力量', '敏捷', '智力', '生命', '魔法', '耐力']
plt.thetagrids(angles, labels)
# 显示
plt.show()运行之后,效果如下图所示。

分析:
对于 plt.thetagrids(angles, labels) 函数来说,如果想要使用第 2 个参数,那么 angles 和 labels 这 2 个列表的元素个数必须相同,然后 labels 的元素会一一替换到 angles 的刻度上去。
2. 填充颜色
在 Matplotlib 中,我们可以使用 fill() 这个函数来对一个雷达图进行填充颜色。
语法:
plt.fill(theta, r, color, alpha)说明:
fill() 函数和 polar() 函数的前 2 个参数是一样的,theta 保存的是所有点的偏移角度,r 保存的是所有点离原点的距离。
参数 color 用于定义填充的颜色,参数 alpha 用于定义透明度(0.0 ~ 1.0)。
示例 5:填充颜色
import numpy as np
import matplotlib.pyplot as plt
# 绘图
theta = np.array([45, 135, 180, 270, 45]) * np.pi / 180
r = [20, 60, 40, 80, 20]
plt.polar(theta, r, marker='o', color='red')
# 刻度范围
plt.ylim(0, 100)
# 填充颜色
plt.fill(theta, r, color='red', alpha=0.5)
# 显示
plt.show()运行之后,效果如下图所示。

分析:
细心的小伙伴可能发现了,在上面的列表中,我们第一个点的数据是 (45, 20),而列表最后的一个数据也是 (45, 20)。
这是因为,极坐标图默认只是把点用线连起来,如果不把第一个点的数据追加到列表的最后,画出来的图形将是“缺一个口子”的。为了让雷达图形成一个封闭的多边形(首尾相连),我们必须手动将第一个数据点复制一份放到列表的最后。
Matplotlib 雷达图案例
相信大多数小伙伴都玩过游戏,对于一个英雄来说,它主要的能力指标有 6 个:力量、敏捷、智力、生命、魔法、耐力。接下来,我们尝试使用雷达图来直观地展示一个英雄的能力是怎样的。
示例 6:Matplotlib 雷达图的应用
import numpy as np
import matplotlib.pyplot as plt
# 设置
plt.rcParams['font.family'] = ['SimHei', 'PingFang SC']
plt.rcParams['axes.unicode_minus'] = False
# 绘图
theta = np.array([0, 60, 120, 180, 240, 300, 0]) * np.pi / 180
r = [9, 6, 3, 9, 3, 8, 9]
plt.polar(theta, r, marker='o', color='red')
# 刻度范围
plt.ylim(0, 10)
# 刻度标签
angles = [0, 60, 120, 180, 240, 300]
labels = ['力量', '敏捷', '智力', '生命', '魔法', '耐力']
plt.thetagrids(angles, labels)
# 填充颜色
plt.fill(theta, r, color='red', alpha=0.5)
# 显示
plt.show()运行之后,效果如下图所示。

分析:
从雷达图可以很直观地看出来,这个英雄其实是一个典型的战士型英雄。相信很多小伙伴都知道 “国乒一哥” 马龙被日本媒体称之为 “六边形战士”,如果用雷达图来表示,应该是下图这样的。

