文章目錄
- 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或者-1ax.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 pifrom 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或者-1ax.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 pifrom 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實現雷達圖的繪制