【Python】レーダーチャートでデータを可視化する

Pythonでは、maptlotlibを用いてレーダーチャートを描画することができます。今回は、レーダーチャートの描画方法を紹介していきたいと思います。

レーダーチャートとは

スパイダーチャートとも呼ばれるこのグラフは、複数の項目のデータを正多角形上に表現したグラフです。

中心を0とし、値が大きくなるにつれ外側にプロットされます。プロットされた点は隣の点と結び、エリアとして表示する場合が多いです。

一般に、各項目間のバランスを見たり、複数のレーダーチャートを並べて(重ねて)性能の比較をしたりする場合に用いられます。

レーダーチャートを描画する

今回使用するデータ

今回は、matplotlib公式のサンプルでも用いられている、デンバーにおける排気ガスと健康に関する研究データの一部を用います。

data = [['Sulfate', 'Nitrate', 'EC', 'OC1', 'OC2', 'OC3', 'OP', 'CO', 'O3'],
        [0.88, 0.01, 0.03, 0.03, 0.00, 0.06, 0.01, 0.00, 0.00],
        [0.07, 0.95, 0.04, 0.05, 0.00, 0.02, 0.01, 0.00, 0.00],
        [0.01, 0.02, 0.85, 0.19, 0.05, 0.10, 0.00, 0.00, 0.00],
        [0.02, 0.01, 0.07, 0.01, 0.21, 0.12, 0.98, 0.00, 0.00],
        [0.01, 0.01, 0.02, 0.71, 0.74, 0.70, 0.00, 0.00, 0.00]]

このデータを使って、1つのグラフに5つのチャートを重ねる図を描画していきます。

ソースコード

まずはソースコード全体を掲載します。その後、内容について説明していきます。

import matplotlib.pyplot as plt
import numpy as np


def plot_rader(labels, values):
    
    #描画領域の作成
    fig, ax = plt.subplots(1, 1, figsize=(5, 5), subplot_kw={'projection': 'polar'})
    
    colors = ['b', 'r', 'g', 'm', 'y']
    
    #チャートを順に描画
    for i, data in enumerate(zip(values, colors)):        
        d = data[0]
        color = data[1]
        
        #要素数の連番作成
        angles = np.linspace(0, 2 * np.pi, len(labels) + 1, endpoint=True)
        #閉じた多角形に変換
        value = np.concatenate((d, [d[0]]))  
        
        #線の描画
        ax.plot(angles, value, 'o-', color=color)
        #塗りつぶし
        ax.fill(angles, value, alpha=0.25, facecolor=color)  

    #軸ラベルの設定
    ax.set_thetagrids(angles[:-1] * 180 / np.pi, labels)  
    #描画開始位置の指定(N: North)
    ax.set_theta_zero_location('N')
    
    plt.show()
    plt.close(fig)
    
#ここから
if __name__ == '__main__':

    data = [['Sulfate', 'Nitrate', 'EC', 'OC1', 'OC2', 'OC3', 'OP', 'CO', 'O3'],
            [0.88, 0.01, 0.03, 0.03, 0.00, 0.06, 0.01, 0.00, 0.00],
            [0.07, 0.95, 0.04, 0.05, 0.00, 0.02, 0.01, 0.00, 0.00],
            [0.01, 0.02, 0.85, 0.19, 0.05, 0.10, 0.00, 0.00, 0.00],
            [0.02, 0.01, 0.07, 0.01, 0.21, 0.12, 0.98, 0.00, 0.00],
            [0.01, 0.01, 0.02, 0.71, 0.74, 0.70, 0.00, 0.00, 0.00]]
    
    plot_rader(data[0], data[1:])

描画はplot_rader()関数内で行っているので、そこを解説します。今回のコードで描画できるグラフは以下のようなものです。

コードの実行結果

描画領域の作成

plt.subplot()で描画する領域を作成します。 subplot_kwではaxのパラメータを辞書型で指定できます。ここではprojection=polarとすることで、円形の極座標グラフを描画することができます。

#描画領域の作成
fig, ax = plt.subplots(1, 1, figsize=(5, 5), subplot_kw={'projection': 'polar'})

チャートを順に描画

今回は5つのチャートをfor文で順に描画していきます。

anglesでは、要素をどの位置にプロットするかという情報を作成します。 np.linspace()は(start, end, 要素数)を指定し、startからendまでの要素数の公差(間隔)を配列で返します。

np.concatenate()は配列を結合するメソッドです。ここでは、valueの最後にvalueの1つ目の要素を追加することで、円形に描画したときに繋がって表示されるようにしています。

ここまできたら、ax.plot()にanglesとvalueを渡して描画します。ax.fillでは、チャートの内側を塗りつぶす設定ができます。alphaは透明度、facecolorで色を指定します。

for i, data in enumerate(zip(values, colors)):        
        d = data[0]
        color = data[1]
        
        #要素描画位置
        angles = np.linspace(0, 2 * np.pi, len(labels) + 1, endpoint=True)
        #閉じた多角形に変換
        value = np.concatenate((d, [d[0]]))  
        
        #線の描画
        ax.plot(angles, value, 'o-', color=color)
        #塗りつぶし
        ax.fill(angles, value, alpha=0.25, facecolor=color)  

円形チャート特有の設定

全てのチャートを一通り描画したら、円形のグラフ特有の設定をしていきます。

ax.set_thetagrids()では、軸ラベルおよびその描画位置を指定します。 angles[:-1] * 180 / np.pi の結果は360°を要素数で等間隔に割ったときの各要素の角度です(今回の要素数は9)。この角度に各ラベルを描画します。

angles[:-1]*180/np.pi
array([  0.,  40.,  80., 120., 160., 200., 240., 280., 320.])

ax.set_theta_zero_location()では要素の描画開始位置を指定します。今回は”N”を渡していますが、これはNorth(北)、つまり12時の方向を起点に描画するように設定しています。

#軸ラベルの設定
ax.set_thetagrids(angles[:-1] * 180 / np.pi, labels)  
#描画開始位置の指定(N: North)
ax.set_theta_zero_location('N')

Pythonでデータサイエンスするなら

Pythonでデータサイエンスをするなら、以下の書籍がおすすめです。Pandas、matplotlib、Numpy、scikit-learnといったデータサイエンスに必要なライブラリを、体系立てて一通り学ぶことができます。

ややお値段高めですが、これ1冊で十分という内容・ボリュームなので、損はしないと思います^^

まとめ

Pythonのmatplotlibでレーダーチャートを描画する方法を紹介しました。他のグラフと違い、描画に角度等の計算が必要だったりとややこしい部分もありますが、やっている処理の内容がわかればそれほど難しくないと思います。

今回のコードを流用するもよし、さらに応用的に使うもよし、お目当てのアウトプットをぜひ作ってみてください。

ではでは👋