文章目录
- 1、功能描述和原理介绍
- 2、代码实现
- 3、效果展示
- 4、完整代码
- 5、多个雷达图绘制在一张图上
- 6、参考
1、功能描述和原理介绍
基于 matplotlib 实现雷达图的绘制
一、雷达图的基本概念
雷达图(Radar Chart),也被称为蛛网图或星型图,是一种用于可视化多个变量之间关系的图表形式。它常用于比较多个变量之间的关系,特别是在展示各个维度的综合表现时非常有用。雷达图的基本构造是一个圆形网格,代表数据的各个维度。每个维度对应一个顶点,这些顶点通过直线连接,形成一个封闭的多边形。
二、绘制原理
-
极坐标系统:
雷达图是基于极坐标系统绘制的。在极坐标系统中,点的位置由角度和半径两个参数决定。
在雷达图中,每个维度对应一个特定的角度,这些角度通常是等间隔分布的。 -
数据映射:
在绘制雷达图之前,需要将数据映射到极坐标系统上。这通常涉及将每个维度的值转换为对应的半径长度。
为了保证各个维度之间的数值比例能够做同级别的比较,通常需要对数据进行标准化处理。 -
绘制多边形:
绘制雷达图时,从中心点开始,按照每个维度的角度绘制射线,并在射线上根据数据的值确定数据点的位置。
将这些数据点依次连接起来,形成一个封闭的多边形,这个多边形就是雷达图的基本形状。 -
区域填充:
为了增强雷达图的视觉效果,通常会对多边形内部进行填充。
填充的颜色、透明度等属性可以根据需要进行调整。
三、matplotlib绘制雷达图的步骤
-
准备数据:
确定要展示的维度和数据集。
对数据进行标准化处理(如果需要)。 -
设置图形大小和子图:
使用 plt.figure() 设置图形的整体大小。
使用 plt.subplots() 或 fig.add_subplot() 创建极坐标子图。 -
绘制雷达图:
使用 ax.plot() 或 ax.fill_between() 等方法绘制雷达图。
设置角度和半径参数,确保数据正确映射到极坐标系统上。 -
设置标签和标题:
使用 ax.set_xticks() 和 ax.set_xticklabels() 设置角度标签。
使用 plt.title() 或 ax.set_title() 设置图形标题。 -
显示图形:
使用 plt.show() 显示绘制好的雷达图。
四、注意事项
- 数据标准化:在绘制雷达图之前,通常需要对数据进行标准化处理,以保证各个维度之间的数值比例能够做同级别的比较。
- 角度设置:角度的设置应确保每个维度都能均匀分布在雷达图上。
- 图形美观:可以通过调整颜色、透明度、线型等属性来增强雷达图的视觉效果。
2、代码实现
原始数据
# 漫威英雄
abilities = ['智力', '力量', '速度', '耐力', '能量', '技能']
super_heros = {
'美国队长': [5, 4, 3, 4, 3, 7],
'钢铁侠': [6, 3, 5, 5, 3, 3],
'绿巨人': [6, 7, 3, 7, 1, 5],
'蜘蛛侠': [5, 4, 5, 4, 2, 5],
'灭霸': [7, 7, 7, 7, 7, 7],
'雷神': [2, 5, 6, 7, 6, 6],
'绯红女巫': [3, 3, 3, 3, 7, 3],
'黑寡妇': [5, 3, 2, 3, 3, 7],
'鹰眼': [5, 3, 3, 2, 2, 7],
}
转化后的数据
list1 = list(super_heros.keys())
print(f"'group':{list1},")
for index, ability in enumerate(abilities):
attrib = []
for item in super_heros:
attrib.append(super_heros[item][index])
print(f"'{ability}':", attrib, end=",\n")
output
'group':['美国队长', '钢铁侠', '绿巨人', '蜘蛛侠', '灭霸', '雷神', '绯红女巫', '黑寡妇', '鹰眼'],
'智力': [5, 6, 6, 5, 7, 2, 3, 5, 5],
'力量': [4, 3, 7, 4, 7, 5, 3, 3, 3],
'速度': [3, 5, 3, 5, 7, 6, 3, 2, 3],
'耐力': [4, 5, 7, 4, 7, 7, 3, 3, 2],
'能量': [3, 3, 1, 2, 7, 6, 7, 3, 2],
'技能': [7, 3, 5, 5, 7, 6, 3, 7, 7],
下面基于处理后的数据绘制雷达图
首先导入必要的库函数
import matplotlib.pyplot as plt
import pandas as pd
from math import pi
配置好支持中文显示
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
配置绘制的数据
# Set data
df = pd.DataFrame({
'group':['美国队长', '钢铁侠', '绿巨人', '蜘蛛侠', '灭霸', '雷神', '绯红女巫', '黑寡妇', '鹰眼'],
'智力': [5, 6, 6, 5, 7, 2, 3, 5, 5],
'力量': [4, 3, 7, 4, 7, 5, 3, 3, 3],
'速度': [3, 5, 3, 5, 7, 6, 3, 2, 3],
'耐力': [4, 5, 7, 4, 7, 7, 3, 3, 2],
'能量': [3, 3, 1, 2, 7, 6, 7, 3, 2],
'技能': [7, 3, 5, 5, 7, 6, 3, 7, 7],
})
步骤1,创建背景
# ---------- 步骤1 创建背景
def make_spider(row, title, color):
# number of variable
# 变量类别
categories = list(df)[1:]
# 变量类别个数
N = len(categories)
# 设置每个点的角度值
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]
# Initialise the spider plot
# 分图
ax = plt.subplot(3, 3, row + 1, polar=True, )
plt.subplots_adjust(wspace=0.3, hspace=0.5)
# If you want the first axis to be on top:
# 设置角度偏移
ax.set_theta_offset(pi / 2)
# 设置顺时针还是逆时针,1或者-1
ax.set_theta_direction(-1)
# Draw one axe per variable + add labels labels yet
# 设置x轴的标签
plt.xticks(angles[:-1], categories, color='grey', size=12) # 最外围
# Draw ylabels
# 画标签
ax.set_rlabel_position(0)
plt.yticks([3, 6, 9], ["3", "6", "9"], color="grey", size=7) # 内圈
plt.ylim(0, 10) # 英雄的各项数值介于 0-10 之间
# Ind
# 填充数据
values = df.loc[row].drop('group').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, color=color, linewidth=2, linestyle='solid')
ax.fill(angles, values, color=color, alpha=0.4)
# Add a title
# 设置标题
plt.title(title, size=15, color=color, position=(0.5, 0.5))
代码解析
九个英雄,布局成 3x3 的形式 ax = plt.subplot(3, 3, row + 1, polar=True, )
可是适当扩大些行列间距,plt.subplots_adjust(wspace=0.3, hspace=0.5)
,防止图形绘制的时候重叠
绘制雷达图
my_dpi = 96
plt.figure(figsize=(1000 / my_dpi, 1000 / my_dpi), dpi=my_dpi)
# Create a color palette:
# 设定颜色
my_palette = plt.cm.get_cmap("gist_rainbow", len(df.index))
# Loop to plot
for row in range(0, len(df.index)):
make_spider(row=row, title='hero ' + df['group'][row], color=my_palette(row))
plt.show()
plt.cm.get_cmap
颜色模式有许多种,可以自己选择
3、效果展示
试试更多的例子
4、完整代码
数据处理
# 漫威英雄
abilities = ['智力', '力量', '速度', '耐力', '能量', '技能']
super_heros = {
'美国队长': [5, 4, 3, 4, 3, 7],
'钢铁侠': [6, 3, 5, 5, 3, 3],
'绿巨人': [6, 7, 3, 7, 1, 5],
'蜘蛛侠': [5, 4, 5, 4, 2, 5],
'灭霸': [7, 7, 7, 7, 7, 7],
'雷神': [2, 5, 6, 7, 6, 6],
'绯红女巫': [3, 3, 3, 3, 7, 3],
'黑寡妇': [5, 3, 2, 3, 3, 7],
'鹰眼': [5, 3, 3, 2, 2, 7],
}
# 火影忍者
abilities = ['忍', '体', '幻', '贤', '力', '速', '精', '印']
super_heros = {
'旗木卡卡西': [10, 9, 8, 10, 7, 9, 6, 10],
'自来也': [10, 9, 6, 9, 9, 9, 10, 9],
'纲手': [10, 10, 7, 10, 10, 7, 8, 8],
'宇智波鼬': [10, 9, 10, 10, 7, 10, 5, 10],
}
list1 = list(super_heros.keys())
print(f"'group':{list1},")
for index, ability in enumerate(abilities):
attrib = []
for item in super_heros:
attrib.append(super_heros[item][index])
print(f"'{ability}':", attrib, end=",\n")
雷达图绘制
import matplotlib.pyplot as plt
import pandas as pd
from math import pi
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# Set data
if 1:
df = pd.DataFrame({
'group':['美国队长', '钢铁侠', '绿巨人', '蜘蛛侠', '灭霸', '雷神', '绯红女巫', '黑寡妇', '鹰眼'],
'智力': [5, 6, 6, 5, 7, 2, 3, 5, 5],
'力量': [4, 3, 7, 4, 7, 5, 3, 3, 3],
'速度': [3, 5, 3, 5, 7, 6, 3, 2, 3],
'耐力': [4, 5, 7, 4, 7, 7, 3, 3, 2],
'能量': [3, 3, 1, 2, 7, 6, 7, 3, 2],
'技能': [7, 3, 5, 5, 7, 6, 3, 7, 7],
})
if 0:
df = pd.DataFrame({
'group':['旗木卡卡西', '自来也', '纲手', '宇智波鼬'],
'忍': [10, 10, 10, 10],
'体': [9, 9, 10, 9],
'幻': [8, 6, 7, 10],
'贤': [10, 9, 10, 10],
'力': [7, 9, 10, 7],
'速': [9, 9, 7, 10],
'精': [6, 10, 8, 5],
'印': [10, 9, 8, 10],
})
# ---------- 步骤1 创建背景
def make_spider(row, title, color):
# number of variable
# 变量类别
categories = list(df)[1:]
# 变量类别个数
N = len(categories)
# 设置每个点的角度值
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]
# Initialise the spider plot
# 分图
ax = plt.subplot(3, 3, row + 1, polar=True, )
plt.subplots_adjust(wspace=0.3, hspace=0.5)
# If you want the first axis to be on top:
# 设置角度偏移
ax.set_theta_offset(pi / 2)
# 设置顺时针还是逆时针,1或者-1
ax.set_theta_direction(-1)
# Draw one axe per variable + add labels labels yet
# 设置x轴的标签
plt.xticks(angles[:-1], categories, color='grey', size=12) # 最外围
# Draw ylabels
# 画标签
ax.set_rlabel_position(0)
plt.yticks([3, 6, 9], ["3", "6", "9"], color="grey", size=7) # 内圈
plt.ylim(0, 10)
# Ind
# 填充数据
values = df.loc[row].drop('group').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, color=color, linewidth=2, linestyle='solid')
ax.fill(angles, values, color=color, alpha=0.4)
# Add a title
# 设置标题
plt.title(title, size=15, color=color, position=(0.5, 0.5))
# ---------- 步骤2 绘制图形
my_dpi = 96
plt.figure(figsize=(1000 / my_dpi, 1000 / my_dpi), dpi=my_dpi)
# Create a color palette:
# 设定颜色
my_palette = plt.cm.get_cmap("gist_rainbow", len(df.index))
# Loop to plot
for row in range(0, len(df.index)):
make_spider(row=row, title=df['group'][row], color=my_palette(row))
plt.show()
5、多个雷达图绘制在一张图上
# Libraries
import matplotlib.pyplot as plt
import pandas as pd
from math import pi
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# Set data
df = pd.DataFrame({
'group': ['旗木卡卡西', '自来也', '纲手', '宇智波鼬'],
'忍': [10, 10, 10, 10],
'体': [9, 9, 10, 9],
'幻': [8, 6, 7, 10],
'贤': [10, 9, 10, 10],
'力': [7, 9, 10, 7],
'速': [9, 9, 7, 10],
'精': [6, 10, 8, 5],
'印': [10, 9, 8, 10],
})
# ---------- 步骤1 创建背景
# number of variable
# 变量类别
categories = list(df)[1:]
# 变量类别个数
N = len(categories)
# 设置每个点的角度值
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]
# Initialise the spider plot
# 初始化极坐标网格
ax = plt.subplot(111, polar=True)
# If you want the first axis to be on top:
# 设置角度偏移
ax.set_theta_offset(pi / 2)
# 设置顺时针还是逆时针,1或者-1
ax.set_theta_direction(-1)
# Draw one axe per variable + add labels labels yet
# 设置x轴的标签
plt.xticks(angles[:-1], categories)
# Draw ylabels
# 画标签
ax.set_rlabel_position(0)
plt.yticks([3, 6, 9], ["3", "6", "9"], color="grey", size=7)
plt.ylim(0, 10)
# ---------- 步骤1 绘制数据
# 单独绘制每一组数据
my_palette = plt.cm.get_cmap("rainbow", len(df.index)) # 颜色
for index in range(len(df["group"])):
values = df.loc[index].drop('group').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, color=my_palette(index),
linewidth=1, linestyle='solid', label=df["group"][index])
ax.fill(angles, values, color=my_palette(index), alpha=0.2)
# Add legend
# 添加图例
plt.legend(loc='upper right', bbox_to_anchor=(0.1, 0.1))
plt.show()
my_palette = plt.cm.get_cmap("rainbow", len(df.index)) # 颜色
可以自由搭配颜色模式
6、参考
- https://github.com/chenqionghe/generate-ability-map/tree/master
- [python] 基于matplotlib实现雷达图的绘制