【Python】matplotlibでグラフの形を整えてみた(サブプロット編その2)

こんにちは、うさじんです。
前回、Pythonのmatplotlibでグラフシートを作りました。

matplotlibはDataFrameとことなり、色々な設定項目があるのが良いですね。
本記事では、matplotlibのsubplotsで異なるアプローチでグラフシートを作ってみました。

前回の記事は以下です。

関連記事

  こんにちは、うさじんです。 本記事では前回、正弦波をpandas.DataFrame.plotでグラフを作りましたが、 それと同じことをmatplotlibのsubplotsで行ってみました。 前回の記[…]

 

前回のコード fig, axes = plt.subplots版

以下が前回のコードです。

import pandas as pd #pandasのインポート
import matplotlib as mpl
from matplotlib import pyplot as plt
import japanize_matplotlib #日本語ライブラリのインポート

#データの1行目を読み込み。
df = pd.read_csv("test_data.csv", skiprows=[1])
df2= df.rename(columns={'Unnamed: 0':'Time[sec]'}) #時刻列の行名を変更
print(df2)

fig, axes = plt.subplots(len(num_list)-1, 1, #サブプロットの行数、列数
              squeeze=False, #squeeze=Falseで二次元配列とする
              figsize=(8, 10), #figureのサイズ
              tight_layout=True) #Tight_layoutの設定
fig.suptitle('サンプルデータ 正弦波(fig, ax = plt.subplots版)', weight=5, fontsize=16) #グラフタイトルの設定、太さ、サイズ

for row in range(len(num_list)-1):
  axes[row, 0].plot(df2.iloc[:,0], df2.iloc[:,row + 1])
  axes[row, 0].set_title(df2.columns[row + 1], loc='left')
  axes[row, 0].grid() #デフォルトはmajor
  axes[row, 0].set_xlabel("time[sec]") #横軸の軸ラベル
  axes[row, 0].set_ylabel("振幅[-]") #横軸の軸ラベル
  axes[row, 0].set_xlim(0, 10) #横軸の最小値、最大値
  axes[row, 0].set_ylim(-1.5, 1.5) #縦軸の最小値、最大値
  axes[row, 0].xaxis.set_major_locator(mpl.ticker.MultipleLocator(1)) #軸目盛りを特定値の倍数当分に分割
  axes[row, 0].yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5)) #軸目盛りを特定値の倍数当分に分割

実行結果

図A 実行結果 fig, axes = plt.subplots版

4つの正弦波データを4行1列のグラフで縦並びにしています。
これは同時系列や同じ横軸を持つデータを比較するときによく使う手法です。

構造物や製品の固有振動数を調査する打撃試験時のデータ、振動試験や現地実稼働データの比較をする際は、
多点計測・分析を行う場合が多く、同基準で評価するためです。

そういったデータをPythonで評価する場合は、matplotlibやDataFrame.plotでグラフ化することが良いと思います。

For文でサブプロットグラフを繰り返して作ることで、コードを大幅に短縮しました。
内容としては、fig, axes = plt.subplots を使い、すでに作成したサブプロットグラフの枠組みに
axesを挿入していくオブジェクト指向のスタイルとなります。

今回のコード plt.subplot版

コードは以下です。

import pandas as pd #pandasのインポート
import matplotlib as mpl
from matplotlib import pyplot as plt
import numpy as np
import japanize_matplotlib #日本語ライブラリのインポート

#データの1行目を読み込み。
df = pd.read_csv("test_data.csv", skiprows=[1])
df2= df.rename(columns={'Unnamed: 0':'Time[sec]'}) #時刻列の行名を変更
print(df2)
num_list = list(df2.columns)#カラムのリスト化

#Figureの作成
fig = plt.figure(figsize=(8, 10), tight_layout=True) #figの設定、余分な余白削除
fig.suptitle('サンプルデータ 正弦波(plt.subplot版)', weight=5, fontsize=16) #グラフタイトルの設定、太さ、サイズ

for row in range(len(num_list)-1):
  plt.subplot(len(num_list)-1, 1, row + 1) #サブプロットの指定、位置
  plt.title(df2.columns[row + 1], loc='left') #グラフタイトルの設定、位置
  plt.plot(df2.iloc[:,0], df2.iloc[:,row + 1]) #グラフデータの指定(x, y)
  plt.grid() #目盛り線を表示(デフォルトはmajor)
  plt.xlabel("time[sec]") #横軸の軸ラベル
  plt.ylabel("振幅[-]") #縦軸の軸ラベル
  plt.xlim(0,10) #横軸の最小値、最大値
  plt.ylim(-1.5, 1.5) #縦軸の最小値、最大値
  plt.xticks(np.arange(0, 10+1, step=1.0)) #軸目盛りを指定値から等間隔に分割
  plt.yticks(np.arange(-1.5, 2, step=0.5)) #軸目盛りを指定値から等間隔に分割

これは plt.subplot で、各データを割り当てるサブプロットの領域を指定していく手法となります。
plt.plot でデータの指定を行い、各グラフの設定項目を指示していきます。

fig, axes = plt.subplots と大きく内容は変わりませんが、
matplotlibのpyplot がもっているインターフェースでグラフの設定をしている形式となります。

私はプログラマではないため、この違いを詳細に説明することが出来ませんが、
同じ出力結果であることはわかりました。

データ計測・分析の現場では、素早く間違いの無いデータ評価が求められます。
前回記事の力任せのコードでは、軸項目の設定に時間を要し、間違いが増える可能性があります。

そのため、コードをできるだけ短くし、効率化が求められる分析作業は大事です。

 

まとめ

個人的にはこちらの plt.subplot のほうが直感的で理解が早かったです。

今回の同じ実行結果を、異なるコードで比較検討した試みは、
今まであやふやであった matplotlib のもやもやを少し明るくしてくれました。

まだ折れ線グラフしか作っていない気がしますが、
今後はFFT(高速フーリエ変換)やローパスフィルタ・ハイパスフィルタ処理等の信号処理や数値計算も行っていきたいと思います。

Pythonはライブラリが豊富で様々な検証を行うことができるため、
その前段階としてmatplotlib やDataFrameの使い方を覚えることができたのは大きな前進でした。

現状VSC(Visual Studio Code)でしかPythonを動かせないため、
Excelマクロでつくるアドインのようにツール化して、グラフデータを表示するようにしてみたくもあります。

今後も様々な技術の実践、検証を行って記事にしてみたいと思います。

よろしくお願いします。