日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

用python繪制極坐標雷達圖_python

作者:伊滴小朋友 ? 更新時間: 2022-04-12 編程語言

綜述

python的matplotlib畫圖庫的功能非常強大,可以畫很多很多種圖,我們日常生活中遇到的雷達圖也不例外。

雷達圖也被稱為網絡圖,蜘蛛圖,星圖等,是一個不規則的多邊形。雷達圖可以形象地展示相同事物的多維指標,應用場景非常多,比如本篇博客中,用來展示球員的不同能力的區別。

matplotlib庫中的雷達圖繪制是基于極坐標的,因此所有的數據和標簽都要根據角度來計算出位置。

本篇博客將詳細的解釋繪制雷達圖過程中的思路、過程以及各個函數方法的詳細解析,如有不正確的地方歡迎大佬指正~

繪圖代碼和解析

繪制一張多主體雷達圖

所謂多主體雷達圖,就是在一張圖中顯示多個多邊形組成的屬性圖,形成直觀的對比。

預處理

對應的包下好,然后解決一下中文和符號顯示的問題,設置默認的字體,修改繪圖樣式;

加載數據集(我這里的數據集來源:某綠色足球app),提取字典中的鍵和值分別保存在labels和score當中。

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['KaiTi']  # 指定默認字體
plt.rcParams['axes.unicode_minus'] = False  # 解決保存圖像是負號'-'顯示為方塊的問題
plt.style.use('ggplot')  # 設置ggplot主題樣式

# 原始數據集并獲取數據集長度
results = [{"速度": 68, "射門": 91, "傳球": 83, "盤帶": 83, "防守": 47, "力量": 82},
           {"速度": 88, "射門": 87, "傳球": 82, "盤帶": 86, "防守": 42, "力量": 69},
           {"速度": 58, "射門": 55, "傳球": 70, "盤帶": 67, "防守": 86, "力量": 77}]
data_length = len(results[0])

 # 將極坐標根據數據長度進行等分,形成角度列表
angles = np.linspace(0, 2 * np.pi, data_length, endpoint=False)

# 分離屬性字段和數據
labels = [key for key in results[0].keys()]
score = [[v for v in result.values()] for result in results]

封閉雷達圖

由于我們畫出來的圖是一個封閉的多邊形,而我們提取出來的score、labels和angles數據的每一項并不是首尾相接的,因此我們需要把每一個列表的第一項copy一下,然后添加到列表末尾。

angles = np.concatenate((angles, [angles[0]]))
labels = np.concatenate((labels, [labels[0]]))
score_Harry = np.concatenate((score[0], [score[0][0]]))
score_Son = np.concatenate((score[1], [score[1][0]]))
score_Tobi = np.concatenate((score[2], [score[2][0]]))

這里因為我弄了三個球員的數據,所以有三條score數據。

提一下np.concatenate函數,這是一個numpy庫中對多個數組進行合并的函數,參數格式為:concatenate((arr1,arr2,arr3),axis=0),第一個括號里面是要合并的數組,可以填任意個,第二個axis參數,與合并方式有關,這里我們用不到就不多贅述了。

繪制圖像

繪制圖像基本跟繪制條形圖的步驟差不多,有幾個可以注意的點:

plot函數中,繪制條形圖是按照“橫坐標-縱坐標”來填寫第一和第二個參數的,由于我們雷達圖是基于極坐標的,matplotlib也很智能的提供了“角度-半徑”的極坐標參數填寫方式;

plot中的顏色只管邊框顏色,fill函數中的顏色是填充顏色,可以自由組合追求美觀;

fill函數中的alpha參數指的是覆蓋區的透明度,越小表示越透明,區間0-1;

plt.legend圖例函數中的loc,是描述圖例位置的

代碼如下:

# 設置圖形的大小
fig = plt.figure(figsize=(8, 6), dpi=100)

# 新建一個子圖
ax = plt.subplot(111, polar=True)

# 繪制雷達圖并填充顏色
ax.plot(angles, score_Harry, color='orange')
ax.fill(angles, score_Harry, 'y', alpha=0.4)
ax.plot(angles, score_Son, color='b')
ax.fill(angles, score_Son, 'cyan', alpha=0.4)
ax.plot(angles, score_Tobi, color='r')
ax.fill(angles, score_Tobi, 'salmon', alpha=0.4)

# 設置雷達圖中每一項的標簽顯示
ax.set_thetagrids(angles * 180 / np.pi, labels, fontsize=15)

ax.set_theta_zero_location('E')  # 設置0度坐標軸起始位置,東西南北

ax.set_rlim(0, 100)  # 設置雷達圖的坐標刻度范圍

ax.set_rlabel_position(270)  # 設置雷達圖的坐標值顯示角度,相對于起始角度的偏移量
ax.set_title("熱刺球員能力對比圖")
plt.legend(["哈里·凱恩", "孫興愍", "托比"], loc='lower left')

plt.show()

完整代碼:

import numpy as np
import matplotlib.pyplot as plt

# 解決中文顯示問題
plt.rcParams['font.sans-serif'] = ['KaiTi']  # 指定默認字體
plt.rcParams['axes.unicode_minus'] = False  # 解決保存圖像是負號'-'顯示為方塊的問題
plt.style.use('ggplot')  # 設置ggplot樣式

# 原始數據集并獲取數據集長度
results = [{"速度": 68, "射門": 91, "傳球": 83, "盤帶": 83, "防守": 47, "力量": 82},
           {"速度": 88, "射門": 87, "傳球": 82, "盤帶": 86, "防守": 42, "力量": 69},
           {"速度": 58, "射門": 55, "傳球": 70, "盤帶": 67, "防守": 86, "力量": 77}]
data_length = len(results[0])

angles = np.linspace(0, 2 * np.pi, data_length, endpoint=False)  # 將極坐標根據數據長度進行等分

# 分離屬性字段和數據
labels = [key for key in results[0].keys()]
score = [[v for v in result.values()] for result in results]

# 使雷達圖數據封閉
angles = np.concatenate((angles, [angles[0]]))
labels = np.concatenate((labels, [labels[0]]))
score_Harry = np.concatenate((score[0], [score[0][0]]))
score_Son = np.concatenate((score[1], [score[1][0]]))
score_Tobi = np.concatenate((score[2], [score[2][0]]))

# 設置圖形的大小
fig = plt.figure(figsize=(8, 6), dpi=100)

# 新建一個子圖
ax = plt.subplot(111, polar=True)

# 繪制雷達圖并填充顏色
ax.plot(angles, score_Harry, color='orange')
ax.fill(angles, score_Harry, 'y', alpha=0.4)
ax.plot(angles, score_Son, color='b')
ax.fill(angles, score_Son, 'cyan', alpha=0.4)
ax.plot(angles, score_Tobi, color='r')
ax.fill(angles, score_Tobi, 'salmon', alpha=0.4)

# 設置雷達圖中每一項的標簽顯示
ax.set_thetagrids(angles * 180 / np.pi, labels, fontsize=15)

ax.set_theta_zero_location('E')  # 設置0度坐標軸起始位置,東西南北

ax.set_rlim(0, 100)  # 設置雷達圖的坐標刻度范圍

ax.set_rlabel_position(270)  # 設置雷達圖的坐標值顯示角度,相對于起始角度的偏移量
ax.set_title("熱刺球員能力對比圖")
plt.legend(["哈里·凱恩", "孫興愍", "托比"], loc='lower left')

plt.show()

最后得到的雷達圖:

在這里插入圖片描述

還是挺好看的(?)

繪制多張單主體雷達圖

數據處理部分跟上面一樣,我們直接從畫圖講起。

建立子圖

首先我們用plt.figure繪制好基本畫布之后,需要建立三個子圖(因為有三個球員):

ax1 = plt.subplot(131, polar=True)
ax2 = plt.subplot(132, polar=True)
ax3 = plt.subplot(133, polar=True)

我們把整個畫布看作一個矩陣,有m行n列;

第一個參數是一個三位數,第一位表示該子圖在整個畫布的行位置,1表示總共把畫布劃分為1行;第二位表示列,3表示總共把畫布劃分為3列;第三個表示索引值,指的是具體的位置,按照從上到下從左到右排列,比如在一個2*2的畫布中,索引值為3表示在第二行第一個;

循環遍歷畫每個子圖

首先把畫圖用的子圖、數據、標簽、顏色都用列表存起來,方便遍歷;

遍歷每一個子圖:

首先畫角度坐標軸和框線,’-.'表示框線的樣式是有一個小線段加一個點組成,lw是linewidth的縮寫,表示線的粗細;

先繪制沿半徑方向的等值線,再繪制角度軸;

繪圖并填充顏色,跟上面一樣;

標出數據下標,ha和va是調整水平和垂直方向的位置

最后調整labels、坐標值范圍等參數

ax, data, name, color = [ax1, ax2, ax3], [score_Harry, score_Son, score_Tobi], ["哈里·凱恩", "孫興愍", "托比"], ["orange", "cyan", "green"]

for i in range(3):
    # 繪制角度軸和框線
    for j in np.arange(0, 100+20, 20):
        ax[i].plot(angles, 7*[j], '-.', lw=0.5, color='black')  #  沿半徑方向的等值線
    for j in range(5):
        ax[i].plot([angles[j], angles[j]], [0, 100], '-.', lw=0.5, color='black')  #  繪制角度軸

    # 繪制圖像并填充顏色
    ax[i].plot(angles, data[i], color=color[i])
    ax[i].fill(angles, data[i], color=color[i], alpha=0.4)

    # 數據下標
    for a, b in zip(angles, data[i]):
        ax[i].text(a, b+5, '%.00f' % b, ha='center', va='center', fontsize=10, color='black')

    # 參數設置
    ax[i].set_thetagrids(angles*180/np.pi, labels)
    ax[i].set_theta_zero_location('N')
    ax[i].set_rlim(0, 100)
    ax[i].set_rlabel_position(0)
    ax[i].set_title(name[i])

最后得到效果(個人審美有限,不喜勿噴):

在這里插入圖片描述

總體來說,強大的matplotlib + 靈活運用代碼 + 美化 = 一幅好看的雷達圖~

總結

原文鏈接:https://blog.csdn.net/qq_45882682/article/details/122796602

相關推薦

欄目分類
最近更新