Pythonのmatplotlibで綺麗なスペクトルを描画する

   Contents

Abstract

Excelでのグラフ描画は直感的で便利ですが、続けていると満足できなくなってくるシチュエーションが出てきます。この記事では、Pythonのmatplotlibを使って綺麗なスペクトルを描画する方法を説明しています。

1. Introduction

研究室内発表や学会発表、論文執筆などの際に、スペクトルデータを見やすいグラフにする作業は日常的に行われています。この時、グラフを見やすくするテクニックを習得するのは独学ではなかなか難しく、研究室の口伝でなんとかしているラボも多いと思います。Chemistry WednesdayのYouTubeチャンネルではExcelを使ってグラフの書式を整える方法を動画で紹介しており、これから初めてグラフを書く学生の参考になればいいな〜と思っているところです。

しかしながら、長らくExcelでグラフを作っていると以下のような点がだんだん気になってきます(気にならなくても気になってきます)。

  • グラフの位置を動かせてしまうので複数のグラフを綺麗に並べたい時に気を遣う
  • 色のグラデーションをつけたい時にRGBとかでいちいち指定しないといけなくて時間がすごくかかる
  • たまに設定できないデザインがある

そんなあなたには、Pythonのライブラリであるmatplotlibを使った自由度・再現性の高いグラフ描画がおすすめです。この記事ではmatplotlibを使ったグラフ描画について簡単に書いていきます。

2. Materials and Methods

僕は基本的にAnaconda環境でJupyter Notebookを使ってコードを書いています。Anacondaのインストール方法はいろんなところで紹介されています。

Python公式
中部大のサイト

Anacondaを入れると必要なライブラリは大体揃った状態になります。

なお、僕が今回使った諸々のバージョンは以下の通りです。

Python 3.9.12
pandas 1.4.2
matplotlib 3.5.1

OSはmacOS Monterey 12.5です。

3. Results and Discussion

matplotlibの使い方は以下のQiitaが網羅的でわかりやすいです。困ったらここを見るといいでしょう。

matplotlibのめっちゃまとめ

今回はData in Brief誌の論文(Grisi, F. et al. Data Br. 2022, 42, 108202.)のNDI-EtCARという化合物のデータを扱います。以下のサイトからzipで諸々ダウンロードできるので、その中のUV_Vis_Excel>UV NDI ET CAR.xlsxをExcelで開いてcsvに変換します(csvをこのサイトに添付したかったけどエラー吐いて断念しました…)。ちなみに論文のライセンスはCC-BYです。

Dataset for norbornene and oxanorbornene dicarboximides functionalized with carbazole and coumarin groups

適当な場所に作業用フォルダを作って、できたcsvファイル(UV NDI ET CAR.csv)を入れておきます。同じ場所にipynbファイル(Jupyter Notebookのプログラムのファイル)を入れておきましょう。Jupyter Notebookを起動して上で作った作業用フォルダに行き、右上の「新規」の「Python 3」みたいなのを押すと新しくipynbファイルが作れます。上の「Untitled」を押すと名前を変えることができます。

最初にコードの全体を貼っておきます。

#モジュールのインポート
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.cm as cm

#csv読み込み
df = pd.read_csv('UV NDI ET CAR.csv')

#グラフの書式を弄る
plt.rcParams['font.family'] = 'Arial'
plt.rcParams['xtick.direction'] = 'in'
plt.rcParams['ytick.direction'] = 'in'
plt.rcParams['font.size'] = 12

#figureを作る。背景を透明にするときはfacecolorなし
fig = plt.figure(figsize=(6,4), dpi=120, tight_layout=True, facecolor='w')

#axesを作る
ax = fig.add_subplot(111)

#プロットする
ax.plot(df['Wavelength (nm)'], df['Abs'], label='NDI-EtCAR', c='r')

#凡例を入れる。fameon=Falseで枠線なし
ax.legend(frameon=False)

#xy軸の範囲を指定。なくてもいいがその場合軸が0にならない
ax.set_xlim(250, 500)
ax.set_ylim(0, 2)

#軸ラベルを入れる。フォントサイズは少し大きくすると見やすい
ax.set_xlabel('Wavelength / nm', fontname='Arial', fontsize=16)
ax.set_ylabel('Absorbance / a.u.', fontname='Arial', fontsize=16)

#軸の目盛りを指定。なくても自動でやってくれる
ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(50))
ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5))

#出力。fig.savefigの方はファイルを出力する
plt.show()
#fig.savefig('figure.png')
こういう感じで出ます。

まずはライブラリをインポートしていきます。一番上のpandasはcsvファイルを読み込む用のやつです。下のコードを書いてShift+Enterで実行して次のセルに行きます。

import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.cm as cm

次にcsvファイルを読み込みます。モノによっては文字コードのエラーとか「列が足りないよ」エラーとかが出ますが、今回のcsvはいい感じなのでエラーなく通るはずです。

df = pd.read_csv('UV NDI ET CAR.csv')

そうするとdfにcsvの内容が入ります。セル(なんか四角く区切ってある領域)に「df」とだけ入れると内容が見れます。

こんな感じ

いい感じですね。

次は早速グラフを書く作業に移っていきます。フォントを指定して、軸目盛りを内側にして、フォントサイズを指定しています。ここら辺は好みですが、以下の設定がおすすめです。

#グラフの書式を弄る
plt.rcParams['font.family'] = 'Arial'
plt.rcParams['xtick.direction'] = 'in'
plt.rcParams['ytick.direction'] = 'in'
plt.rcParams['font.size'] = 12

次はfigureを作成です。ここでいうfigureは、イメージ的にはグラフの台紙みたいなイメージで、Excelでいうところのグラフエリアです。figsizeでサイズ指定、dpiで解像度指定、facecolorで背景色を指定してます。tight_layoutは最後いい感じに軸ラベルとかを配置する指令なので入れるのがおすすめです。

#figureを作る。背景を透明にするときはfacecolorなし
fig = plt.figure(figsize=(6,4), dpi=120, tight_layout=True, facecolor='w')

次にaxesを作ります。axesはグラフ本体のイメージで、Excelでいうところのプロットエリアです。「111」は縦横を1×1に分割した時の1番目に置きます!という意味です。

#axesを作る
ax = fig.add_subplot(111)

そんでついにプロットです。括弧の中の最初がx、二個目がyの配列を入れます。pandasのDataFrameはdf[‘列名‘]で列の配列(pandas.series)になるのでそれを入れます。labelはあとで凡例になります。cは色で、’r’は赤、’b’は青、’k’は黒、みたいな感じです。ここで色々見れます。

#プロットする
ax.plot(df['Wavelength (nm)'], df['Abs'], label='NDI-EtCAR', c='r')

次に凡例を入れます。デフォルトだと灰色の枠線がつきますが、個人的に邪魔なのでframeon=Falseを入れて消します。

#凡例を入れる。fameon=Falseで枠線なし
ax.legend(frameon=False)

次にxy軸の範囲を指定します。指定しなくてもプロットできますが、その場合軸が0にならないので全体的に浮いた感じのグラフになります。適宜いい感じにします。

#xy軸の範囲を指定。なくてもいいがその場合軸が0にならない
ax.set_xlim(250, 500)
ax.set_ylim(0, 2)

軸ラベルを入れます。ギリシャ文字を入れたいときは$で囲ってLatex記法で書きます。例えば$\lambda$でλになります。\(バックスラッシュ)はoption+¥で打てます。フォントサイズは少し大きくすると見やすいです。

#軸ラベルを入れる。フォントサイズは少し大きくすると見やすい
ax.set_xlabel('Wavelength / nm', fontname='Arial', fontsize=16)
ax.set_ylabel('Absorbance / a.u.', fontname='Arial', fontsize=16)

次に軸の目盛りを指定します。ここは正直なくても自動でいい感じにしてくれますが、たまにうるさいときはこれを入れます。

#軸の目盛りを指定。なくても自動でやってくれる
ax.xaxis.set_major_locator(mpl.ticker.MultipleLocator(50))
ax.yaxis.set_major_locator(mpl.ticker.MultipleLocator(0.5))

最後に出力です。普段見るだけのときはplt.show()の方を打ちますが、画像ファイルで欲しいときはfig.savefig(‘figure.png’)の方にします。”の中は好きなファイル名を入れてください。毎回fig.savefigしてると訳わからなくなりがちなので、普段はコメントアウトしてます。

#出力。fig.savefigの方はファイルを出力する
plt.show()
#fig.savefig('figure.png')

これで無事いい感じのグラフがプロットできました。

ちなみに、書式無視でパパッと見たいときは以下の書き方ですぐ出ます。

import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('UV NDI ET CAR.csv')
plt.plot(df['Wavelength (nm)'], df['Abs'])
plt.show()
こんな感じ

この書き方はMATLABスタイルというやつで、簡単に書けますが書式設定の自由度が低いです。ここら辺は以下のサイトが参考になります。

matplotlib の2つの流儀( MATLAB・オブジェクト指向スタイル)

4. Conclusion

matplotlibを使っていい感じのグラフを書く方法を書きました。一つグラフを書くだけならExcelの方が簡単ですが、何個も同じ書式でグラフを書くとなるとpythonが早いしストレスも少ない気がします。一回慣れてしまえばあとは楽なので、エイヤっと覚えてしまうのがおすすめです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です