Pythonでレーダーチャート(Radar Chart)を簡単にプロットする
個人開発しているmatplotlibベースの円形データプロットライブラリ「pyCirclize」に新しく実装したレーダーチャートのプロット機能をこの記事では紹介します。
↓こんな感じのレーダーチャートが簡単に作成できます。
開発目的
レーダーチャートはそれほど多く使う図ではないですが、学生時代に模試の平均点と自分の点数の比較などで見る機会はそれなりにあったので、ほとんどの人に馴染みがある図だと思います。よく知られている図なのでPythonでも既にレーダーチャートをプロットするライブラリもいくつかあると思いましたが、いい感じのライブラリは見当たらなかったです。そこで、個人開発しているpyCirclizeに新しくレーダーチャートのプロット機能を追加してみた。
pyCirclizeのインストール方法
pyCirclizeはPyPIとconda-forgeにそれぞれパッケージを登録しているので、pip
またはconda
コマンドでインストール可能です。
PyPIパッケージ
pip install pycirclize
Condaパッケージ
conda install -c conda-forge pycirclize
レーダーチャートプロット例
pyCirclizeではCircos.radar_chart()
メソッドでpandasデータフレームから簡単にレーダーチャートをプロットできます。以下にRPGでよく見かける職業ごとのパラメータを表現するレーダーチャートのプロットコード例をいくつか挙げます。
1. 標準プロット例
from pycirclize import Circos
import pandas as pd
# Create RPG jobs parameter dataframe (3 jobs, 6 parameters)
df = pd.DataFrame(
data=[
[80, 80, 80, 80, 80, 80],
[90, 95, 95, 30, 30, 80],
[60, 20, 20, 100, 90, 50],
],
index=["Hero", "Warrior", "Wizard"],
columns=["HP", "ATK", "DEF", "SP.ATK", "SP.DEF", "SPD"],
)
print(df)
# Initialize Circos instance for radar chart plot
circos = Circos.radar_chart(
df,
vmax=100,
grid_interval_ratio=0.2,
)
# Plot figure
circos.savefig("example01.png")
HP ATK DEF SP.ATK SP.DEF SPD
Hero 80 80 80 80 80 80
Warrior 90 95 95 30 30 80
Wizard 60 20 20 100 90 50
2. マーカー・凡例付プロット例
from pycirclize import Circos
import pandas as pd
# Create RPG jobs parameter dataframe (3 jobs, 7 parameters)
df = pd.DataFrame(
data=[
[80, 80, 80, 80, 80, 80, 80],
[90, 20, 95, 95, 30, 30, 80],
[60, 90, 20, 20, 100, 90, 50],
],
index=["Hero", "Warrior", "Wizard"],
columns=["HP", "MP", "ATK", "DEF", "SP.ATK", "SP.DEF", "SPD"],
)
print(df)
# Initialize Circos instance for radar chart plot
circos = Circos.radar_chart(
df,
vmax=100,
marker_size=6,
circular=True,
cmap="Set2",
grid_interval_ratio=0.25,
)
# Plot figure & set legend on upper right
fig = circos.plotfig()
_ = circos.ax.legend(loc="upper right")
fig.savefig("example02.png")
HP MP ATK DEF SP.ATK SP.DEF SPD
Hero 80 80 80 80 80 80 80
Warrior 90 20 95 95 30 30 80
Wizard 60 90 20 20 100 90 50
3. 詳細な設定をしたプロット例
from pycirclize import Circos
import pandas as pd
# Create RPG jobs parameter dataframe (4 jobs, 8 parameters)
df = pd.DataFrame(
data=[
[80, 80, 80, 80, 80, 80, 80, 80],
[90, 20, 95, 95, 30, 30, 80, 70],
[60, 90, 20, 20, 100, 90, 50, 70],
[70, 50, 60, 40, 60, 40, 100, 60],
],
index=["Hero", "Warrior", "Wizard", "Assassin"],
columns=["HP", "MP", "ATK", "DEF", "SP.ATK", "SP.DEF", "SPD", "LUK"],
)
print(df)
# Initialize Circos instance for radar chart plot
circos = Circos.radar_chart(
df,
vmax=100,
fill=False,
marker_size=6,
bg_color=None,
cmap=dict(Hero="salmon", Warrior="skyblue", Wizard="lime", Assassin="magenta"),
grid_interval_ratio=0.1,
grid_label_formatter=lambda v: f"{v:.1f}pt",
label_kws_handler=lambda _: dict(style="italic"),
line_kws_handler=lambda _: dict(lw=2, ls="solid"),
marker_kws_handler=lambda _: dict(marker="s", ec="grey", lw=0.5),
)
circos.text("RPG Jobs Radar Chart", r=125, size=15, weight="bold")
# Plot figure & set legend on upper right
fig = circos.plotfig()
_ = circos.ax.legend(
loc="upper right",
bbox_to_anchor=(1.05, 1.05),
fontsize=10,
title="RPG Jobs",
)
fig.savefig("example03.png")
HP MP ATK DEF SP.ATK SP.DEF SPD LUK
Hero 80 80 80 80 80 80 80 80
Warrior 90 20 95 95 30 30 80 70
Wizard 60 90 20 20 100 90 50 70
Assassin 70 50 60 40 60 40 100 60
4. Subplotsへの複数プロット例
from pycirclize import Circos
import pandas as pd
import matplotlib.pyplot as plt
# Create RPG jobs parameter dataframe (4 jobs, 8 parameters)
df = pd.DataFrame(
data=[
[80, 80, 80, 80, 80, 80, 80, 80],
[90, 20, 95, 95, 30, 30, 80, 70],
[60, 90, 20, 20, 100, 90, 50, 70],
[70, 50, 60, 40, 60, 40, 100, 60],
],
index=["Hero", "Warrior", "Wizard", "Assassin"],
columns=["HP", "MP", "ATK", "DEF", "SP.ATK", "SP.DEF", "SPD", "LUK"],
)
print(df)
# Create 2 x 2 subplots
fig = plt.figure(figsize=(16, 16), dpi=100)
fig.subplots(2, 2, subplot_kw=dict(polar=True))
fig.subplots_adjust(wspace=0.15, hspace=0.15)
# Plot radar chart into subplots for each target
for target_name, ax in zip(df.index, fig.axes):
target_df = df.loc[[target_name]]
# Initialize Circos instance for radar chart plot
circos = Circos.radar_chart(
target_df,
vmax=100,
marker_size=6,
cmap=dict(Hero="salmon", Warrior="skyblue", Wizard="lime", Assassin="magenta"),
grid_interval_ratio=0.2,
line_kws_handler=lambda _: dict(lw=2, ls="solid"),
marker_kws_handler=lambda _: dict(marker="D", ec="grey", lw=0.5),
)
# Plot figure & set legend on upper right
circos.plotfig(ax=ax)
circos.ax.legend(loc="upper right", fontsize=10)
fig.savefig("example04.png")
HP MP ATK DEF SP.ATK SP.DEF SPD LUK
Hero 80 80 80 80 80 80 80 80
Warrior 90 20 95 95 30 30 80 70
Wizard 60 90 20 20 100 90 50 70
Assassin 70 50 60 40 60 40 100 60
その他の既存ライブラリ
-
matplotlib
公式ドキュメントにレーダーチャートをプロットする例が紹介されていますが、少し複雑なコード例なので改変して自分の思い通りのものを作ろうとするとそれなりに苦労すると思う。 -
plotly
こちらも公式ドキュメントにプロット例が紹介されていますが、デフォルトのデザインがいまいちに感じました。私自身がplotlyを十分に習熟していないのも一因ですが、より良いデザインを求めて改変しようとすると苦労しそう。インタラクティブな操作ができる点では優れているという印象です。
最後に
レーダーチャートくらいに有名なグラフであれば、扱いやすいPythonライブラリを誰かが作っているだろうと思いましたが、めぼしいものがなかったので自分で作ってみた。pyCirclizeはテーブルデータから簡単にレーダーチャートを作成できるので、Pythonでレーダーチャートをプロットしたいという方がいれば試してみてください。
Discussion