前回の記事では、PandasとMatplotlibを利用してデータを視覚化する実習問題を扱った。
今回は、Matplotlibで複数のグラフを一度に描くことができるsubplotsについて調べる。
1. Subplots
subplotsはグラフを描画するスペースの座標を受け取り、全体のグラフと各グラフの軸を返す。
fig, axis = plt.subplots(2,2, constrained_layout=True)
axisaxisの内容を確認すると、それぞれの軸が2行2列の形式で含まれていることがわかる。
すべてオブジェクトなので、別々に扱うことが可能である。

Jupyterノートブックでは、グラフもすぐに描画される。
まだデータが入っていないため、何もない4つのグラフが現れる。

グラフを1つずつ埋めてみよう。 同じx値に異なるy値を持つグラフを描いてみた。
axisの形が以下のコメントと同じなので、座標のようにアクセスすればよい。
x = [1,2,3,4,5]
y1 = [1,2,3,4,5]
y2 = [1,3,5,7,9]
y3 = [1,4,9,16,26]
y4 = [1,8,27,64,125]
# axis内部は左上から右方向に
# [[最初、2番目],[3番目、4番目]] グラフオブジェクトが含まれている。
axis[0][0].plot(x,y1)
axis[0][1].plot(x,y2)
axis[1][0].plot(x,y3)
axis[1][1].plot(x,y4)
fig上のコードと下の画像を比較すると、どのようにマッピングされているかが見える。

それぞれのグラフオブジェクトにアクセスして詳細な修正を加えることができる。
以前にpltで使った関数の前にset_を付けてください。
axis[0][0].plot(x,y1, label="y=x")
axis[0][0].set_title("最初のグラフ")
axis[0][0].set_xlabel("これはx軸")
axis[0][0].set_ylabel("これはy軸")
axis[0][0].set_xticks(x)
axis[0][0].set_yticks(y1)
axis[0][0].legend()下のように最初のグラフがよく修正されたことが見える。

他のグラフも同様に修正してみよう。
ハードコーディングで修正するのは素晴らしくないので、2重for文でそれぞれのオブジェクトにアクセスして修正してみよう。
x = [1,2,3,4,5]
y1 = [1,2,3,4,5]
y2 = [1,3,5,7,9]
y3 = [1,4,9,16,26]
y4 = [1,8,27,64,125]
# y値と凡例が含まれるリストを作成
# numsを利用して4つの値を回しながら追加できるようにする
ys = [y1,y2,y3,y4]
legends = ["y=x", "y=2x-1", "y=x^2", "y=x^3"]
nums = 0
# for文を2重に回して (0,0), (0,1), (1,0), (1,1)を巡回する
for i in range(2):
for j in range(2):
# x値とysにあるnums番目の値を追加
axis[i][j].plot(x,ys[nums], label=legends[nums])
axis[i][j].set_title(f"{nums+1}番目のグラフ")
axis[i][j].set_xlabel("これはx軸")
axis[i][j].set_ylabel("これはy軸")
axis[i][j].set_xticks(x)
axis[i][j].set_yticks(ys[nums])
axis[i][j].legend()
nums += 1
fig最後のグラフの軸が少し気に入らないが、すべてよく修正された。

2. 活用例
前回、年代別犯罪発生件数、検挙件数をsubplotsでグラフを描いてみよう。
当然ながらPandasで先に値を読み込む。
import pandas as pd
# モジュールの呼び出しと韓国語フォント設定
import matplotlib.pyplot as plt
import matplotlib
# MacOSでのフォント設定
# matplotlib.rcParams["font.family"] = "AppleGothic"
# Windowsでのフォント設定
matplotlib.rcParams["font.family"] = "Malgun Gothic"
# フォントサイズ設定
matplotlib.rcParams["font.size"] = 13
# マイナス出力問題解決
plt.rcParams['axes.unicode_minus'] = False
crime = pd.read_excel("./crime_statistics.xlsx")
crime.head(3)

データの列の中で'ハッキング'を含むものをすべて探してみた。
グラフは合計で4つなので、4つの列だけ選択するようにリストを短くした。
そしてxを年、y1をデータ中の発生件数、y2を検挙件数に指定した。
cols = [i for i in crime.columns if "ハッキング" in i]
cols = cols[:4]
x = crime.iloc[:,0].unique()
y1 = crime.loc[crime.구분=="発生件数",cols[0]]
y2 = crime.loc[crime.구분=="検挙件数",cols[0]]
これで最初のグラフを描いてみた。
fig, axis = plt.subplots(2,2, constrained_layout=True)
axis[0][0].plot(x,y1,label="発生件数")
axis[0][0].plot(x,y2,label="検挙件数")
axis[0][0].legend()
axis[0][0].set_title(cols[0])
axis[0][0].legend()グラフがうまく描かれた。凡例の位置や文字サイズが少し気に入らないが、これは一旦まず描いてから修正すれば良いことだ。
これから、コードを2重for文にして全体のグラフを描くように作成する。

全体のコードをfor文の中に入れ、変更すべき部分を変更する。
まず軸部分をaxis[i][j]に変更するが、1つずつ変更するのが面倒でかっこよくない。
Alt + Shift + マウスドラッグでマルチカーソルが有効化される。
[0][0]部分を消して[i][j]に変更する。


コードをすべて修正すると以下のようになる。
これを実行するとグラフがうまく描かれる。
fig, axis = plt.subplots(2,2, constrained_layout=True)
col_nums = 0
for i in range(2):
for j in range(2):
y1 = crime.loc[crime.구분=="発生件数",cols[col_nums]]
y2 = crime.loc[crime.구분=="検挙件数",cols[col_nums]]
axis[i][j].plot(x,y1,label="発生件数")
axis[i][j].plot(x,y2,"--",label="検挙件数")
axis[i][j].legend()
axis[i][j].set_title(cols[col_nums])
axis[i][j].legend()
col_nums += 1凡例が気に入らないなら、fontsizeパラメータで文字のサイズを小さくしたり、bbox_to_achorを利用して凡例の位置を変更することができる。

これでコードが完成した。他のデータを確認したい場合はcolsに含まれる列名を変更するだけでいい。
今回は『賭博』に変えてみた。
そして他のコードを実行すると自動で賭博に関するグラフが描かれる。


今回はサイバー金融犯罪に関するグラフを描いてみよう。

グラフを見ると犯罪の様相が2016年~2018年を境に多く変化したことがわかる。

3. 記事を締めくくり
今日はmatplotlibでsubplotsを利用する方法について調べた。
ここでは単純にplotだけを使用してグラフを描いたが、これ以外に棒グラフ、水平バー、バイオリンプロットなど多様なグラフを適用できる。
次回はnumpyというモジュールを利用して線形回帰分析グラフを描いてみることにしよう。
댓글을 불러오는 중...