Matplotlibでレポート用グラフ作成~よく使うもの~
特定の点・範囲の強調、グラフの中へのグラフの挿入、拡大図の添付、複軸化、(特に)ヒストグラム、軸目盛の調整......
Excelでこのような細かい要望に合ったグラフを作るのはさすがに大変。多少は自由度が高いだろうとPython+matplotlibでグラフを書いています。ところが、今度はいちいち細かいことが多くて覚えられない!(毎回、前回使ったプログラムを探すところから始まる...)。そしてグラフの見た目を変えるのが超大変!
以下では私が今まで使ってきたもので便利だなあと思いながら、覚えられなくて毎回前回使ったプログラムを探すこととなっているものを載せました。要するにメモです。適宜追加していきます。
以下のコードはいつものテンプレート(スタイル関連を除く)なのでこれを基準にメモしました。
from matplotlib import pyplot as plt from matplotlib import font_manager as fm from matplotlib import rcParams from matplotlib import patches from matplotlib.ticker import ScalarFormatter fontsize = 25 fig, ax1 = plt.subplots(figsize=(8, 6), constrained_layout=True)
▼環境
- Python 3.8
- matplotlib 3.3.4
▼コンテンツ
- 【便利】ダミープロット
- 単位変換した軸を一緒に描画したい
- 画像化と保存、トリミングの手間を省いて、解像度も上げる
- 水平位置と垂直位置
- 複数軸グラフ
- 階級分けした後のヒストグラム
- Texを使いたい
- スケール関連
- 描画順番と重なり
- 軸のメモリやラベルを削除したい
【便利】ダミープロット
例えばax.plot()
に回帰曲線、ax.scatter()
に測定点を書いた場合で凡例を表示させると、普通はax.plot()
由来の線か、ax.scatter()
由来のシンボル(丸とか、三角とか)しか表示されません。ax.plot()
のキーワードでmarker
キーワードを使うと、この場合一般の回帰曲線を考えているので、どえらいことになるのは簡単に想像できます。回帰曲線上に測定点のシンボルを載せたような凡例が欲しい!そういう時はダミープロットを使います。
ax1.plot(回帰曲線のx軸データ, 回帰曲線のy軸データ, color) ax1.scatter(測定点のx軸データ, 測定点のy軸データ, color, marker="o") ax1.plot([], [], color, marker="o", label="ダミープロット!")
ax.plot()
とax.scatter()
両方のスタイルに合わせたダミープロットを作ります。marker
、color
、linestyle
を統一する必要があります。
単位変換した軸を一緒に描画したい
ax.secondary_yaxis([単位を変換した軸をどこに表示するか], functions=(元の単位を目的の単位に変換する関数, 目的の単位から元の単位に変換する関数))
を使います。例えば、単位がラジアンで与えられるデータがあって、これをy軸に表示しているとしましょう。このデータに対応するように度数での表示を行いたいとします。このときは次のようにします。
def rad2degree(x): return np.rad2deg(x) def degree2rad(x): return np.deg2rad(x) secondary_ax = ax1.secondary_yaxis( "right", functions=(rad2degree, degree2rad))
単位を変換した軸を一緒に載せておくと、考察が捗ることがあるので使っています。ax.secondary_yaxis()
はx軸版もありax.secondary_xaxis()
で同様のことができます。こちらもよく使います。
ちなみに、逆関数を定義できない領域があるときは事前にax1.set_ylim()
等で制限をかけておかないとエラーが出ます。例えば、np.arccos()
の定義域は-1から1ですが、そのままプロットすると-2とかまで計算することになって、NaNやInfのデータが生じ、エラーとなります。故に逆関数の定義域については慎重に検討して、すべての実数をとれるわけではないときは、その範囲に合うように表示範囲を狭め、clip_on
などで端の処理をする必要があります。
画像化と保存、トリミングの手間を省いて、解像度も上げる
やり方はplt.savefig
にてpad_inches
キーワードで余白の大きさを指定(小さいほど余白が小さくなります)、dpi
キーワードで解像度を指定(大きいほど解像度がよくなります)するだけです。以下の例では、matplotlibではしばしばあるラベルや軸が見切れてしまう現象を回避するためのキーワードのbbox_inches
を入れています。私はpad_inches=0.11
程度で満足していますが、もっと小さい値でもいいかもしれません。
plt.savefig("filename.jpg", bbox_inches="tight", pad_inches=0.11, dpi=300)
ちなみに.pdf
や.svg
(ベクター画像)にも対応しているようです。
水平位置と垂直位置
図中にテキストを書き込むときに水平位置と垂直位置を指定すると便利がよいことが多いです。簡単に言うと、テキストの書かれた四角い箱:テキストボックスを考えたときに、ボックスのどの値を指定した座標に持ってくるか?を決定するということですね。
ax1.text(x, y, text, fontsize, horizontalalignment="left", verticalalignment="bottom")
例えばこの場合だと、水平方向をhorizontalalignment
でleft
、垂直方向をverticalalignment
でbottom
としているので、テキストボックスの左下の座標が引数(x, y)
で指定した座標になるように描画されます。
複数軸グラフ
変数が同じで、しかし全く別のグラフを同時に描画したいときがあります。例えば、吸光スペクトルと蛍光スペクトルは波長という変数は同じですが、強度は任意単位で別物なので、別々に描画します。同じ変数なので1つのグラフに横軸だけ同じにして描画できるとわかりやすくて良いです。この時はax.twinx()
を使います。
ただしこれだけではax.legend
は元の軸の値しか描画しません(ax1を作って、ax2=ax1.twinx()
としてax1.legend()
とすると、ax1
に描画したもののラベルだけが表示されます)。そこで新しい軸のラベルもまとめて描画するように、次の例でいうところの最後の三行を加えます。
fig, ax1 = plt.subplots(figsize=(8, 6)) ax1.plot(波長, 吸収スペクトルの強度) ax2 = ax1.twinx() ax2.plot(波長, 蛍光スペクトルの強度) handler1, label1 = ax1.get_legend_handles_labels() handler2, label2 = ax2.get_legend_handles_labels() ax1.legend(handler1 + handler2, label1 + label2)
ax.get_legend_handles_labels()
でラベルを表示するためのhandle
と対応するlabel
が得られますが、これらを足し合わせてあげるだけです。足し合わせる順番によって、表示される順番が変わります。
階級分けした後のヒストグラム
例えばすでに4階級に分けた離散データを格納した一次元配列data
を得られたとしましょう。その時は次のようにすればよいです。
ax1.hist(data, bins=4)
連続データの場合も似た感じなので略。ヒストグラムのためにExcelではなくpython + matplotlibを使っているまであります。
Texを使いたい
ラベルに記号や数式を入れたいときがあります。もちろん「γ」のようにあらかじめ存在している特殊記号を使うのもありですが、$\gamma$
のようにできると、つまりTexが使えると非常に便利です。例えば単位の上付き文字をいちいち座標指定するのは馬鹿らしいので$\mathrm{m^2}$
のようにできればなんと便利なことか!(Excelではいちいち右クリックが必要でめんどくさい)。これをやるには当該文字列を$
でラップします:
ax1.text(x, y, "$\gamma$")
ただ、これだけでは$
も含めた文字列だとみなされるのがほとんどなので、さらにr
を先頭につけてr構文にしておきます:
ax1.text(x, y, r"$\gamma$")
ところで数式を改行するときはどうすればいいでしょうか。例えば2行に改行するときは、次に示すように2つの変数を用意するのが後で見たときにわかりやすいと思います:
text1 = r"$y = f(x; t)$" text2 = r"$R^2 = 1.000$" ax1.text(x, y, text1 + "\n" + text2)
では変数を文字列に組み込みたいときはどうしましょうか。次に示す方法は、直接変数を組み込む方法です。
text1 = r"$y = f(x; t=" + str(100) + r")$" text2 = r"$R^2 = 1.000$" ax1.text(x, y, text1 + "\n" + text2)
Texではことあるごとに{}
が出てくるので、フォーマット構文やf構文が使えないと思います(使えましたっけ)。したがって直接結合する方法が一番楽なのではないかなと思います。管理がめんどくさくなりますが、確実です。
スケール関連
わかりやすさを考えて単位を変えることがありますが、単位を変えずに表示したいときがあります。例えばはですが、これをそのままmatplotlibで表示すると「10e9」のように表示されて、わかりにくい...というか、特定の分野の人が好きそうな表示になります。できれば10のなんちゃら乗として表示したい。そこでmatplotlib.ticker.ScalarFormatter
を使います。
ax1.yaxis.set_major_formatter(ScalarFormatter(useMathText=True))
また、対数スケールは次のようにして実現します。例えばy軸を対数スケールにするには
ax1.set_yscale("log")
でよいです。
描画順番と重なり
matplotlibの描画順番はよくわかりません...。先に描画したはずのものが背面に向かっていたり。。。それを調整できるのがzorder
キーワードです。次の例ではラベル"first"のデータの方がラベル"second"のデータよりも上側に(画面手前側に)描画されます。zorder
の値が大きいほど画面手前側に描画され、小さいほど画面反対側の方向に描画されます。負の値をとることもできるので、例えばx軸やy軸などはzorder=-1
などとしておいてもよいかもしれません。
ax1.plot(x1, y1, label="first", zorder=100) ax1.plot(x2, y2, label="second", zorder=1)
ところで、matplotlibのfigureの枠に被せたいのだけど...と思われる方もいるかもしれません。どういうことかというと、例えば(0, 0)にデータ点があって、描画範囲を0以上に設定すると、0番目の点がグラフ領域の外黒枠線の下敷きになってしまうのです。これを回避するには、clip_on
キーワードを使います。clip_on=False
で、グラフの枠や余白によって消される部分が消されないようになります(逆に言えば範囲指定を誤ると大変なことになります)。
ax1.scatter(x1, y1, label="first", zorder=100, clip_on=False) ax1.plot(x2, y2, label="second", zorder=1, clip_on=False)
軸のメモリやラベルを削除したい
例えば任意単位のもので、メモリが不要!ラベルもいらない!といった要望があったとします。そういうときは次のようにします。
ax1.tick_params( labelbottom=False, labelleft=True, labelright=False, labeltop=False, bottom=False, left=True, right=False, top=False )
この例では、左の軸のメモリとラベル以外のすべてのメモリとラベルが削除されます(表示されません)。
レポートをLatexで書く。私にとっての便利部品集。
お久しぶりです。生きています。
大学の講義のレポートを勝手にLatexで書くようになって早1年が経ちました。私にとってLatexは痒い所に手が届く良いものなのですが、自由度が高い故に色々とやることと方法があって大変。今時素のLatexを書く人はいないと思うのですが、1年間Latexと戯れた中で筆者が便利だと感じたものを述べておきます。......というより、毎回忘れてしまうので忘れ防止にメモしておきたい。
実際使ってみて便利だったものを集めた工夫・部品集です。
あまりLatexについて理解を深めているわけではないので、間違っている点があったらご指摘いただけると幸いです。
なお環境は次の通りです。
- OS ... Windows 10
- ドキュメントクラス ... jsarticle
- 処理系 ... uplatex + dvipdfmx
適宜追加していきます。
▼コンテンツ
- 【便利】余白調整
- 【便利】二段組みとぶち抜き
- 【便利】ファイルの分割
- キャプションや表番号などを調整
- 化学スキームに番号を振る
- 参考文献の番号を上付きに
- 図の位置
- 単位→siunitx、化学式→mhchem
- URLと漢字
- 小ネタ系
Raspberry Pi 4 便利な機能の導入メモ:AFP/Samba、イヤホン、スクショ、exFAT対応
こんにちはAxifofです。Raspberry Pi 4B (raspi) はにあると便利だな、設定できていると便利だなと私が感じたもののインストールの仕方を書いておきます。ファイル共有システム netatalk、イヤホンジャックの利用設定、scrot でスクショの撮影、exFAT フォーマット HDD への対応を書きました。
この記事は 2020/07/27 のものです。
[目次]
- 環境等
- raspi4
- Mac
- netatalk で Mac とファイル共有
- 注意
- nano エディタ
- イヤホンジャックから音を出力させる
- scrot でスクリーンショットを取得する
- exFAT HDDの読み書き
Raspberry Pi 4, デフォルトPython 3.7.3 + OpenCVは構成できた。しかし pyenv + OpenCV はできなかった。
こんにちはAxifofです。Raspberry Pi 4 にて Python3 OpenCV をインストールしたときに詰まった話をします。もともと pyenv を導入したのですが opencv の導入がうまく行きませんでした。当たり前かもしれませんが、管理者権限で実行したものと、管理者権限なしで実行したものの結果は異なることが多いです;pyenv global X.X.X
で設定した python
とsudo python
の実行結果は、デフォルトでは異なります。ですから、sudo pip3 install
とpip3 install
は全く別の結果を返します。インストールできない!と騒いでいましたが、ただ私の理解不足が原因でした。
[目次]
- 環境等
- pyenv の導入と python 3.8.4 のインストール
- sudo pip3 install で OpenCV の導入に成功
- 問題発生:インストールしたはずなのに、pyenv の python では cv2 が読み込めない
- python 3.7.3 の環境で事足りるならそれで十分な可能性あり
Mac OS X shred コマンド導入とデータ削除
Axifof です。ファイル削除、HDDデータ削除の際に、修復不能(と考えられる)方法で削除するために、Mac OS X に shred コマンドを導入する話です。普段 Linux を使っていて、最近 Mac に乗り換えたのですが、shred コマンドが見当たらなかったので GNU Coreutils で導入しました。
brew install coreutils
によって、GNU Coreutils をインストールします。この中に shred コマンドが含まれています。削除したいファイル/フォルダ A, B, C に対して
sudo shred -uvz A B C
のように実行します。
コマンドとその内容は以下の表を参照ください[2]。だいたいこのぐらいのコマンドを覚えておけば良いと思います。
オプション | 内容 |
---|---|
-v | コマンドの実行状況を表示します。 |
-u | 上書き後にファイルを削除します。 |
-z | 上書き後に0で上書きをします。 |
-n | 乱数上書き回数の指定をします。デフォルトでは3です。 |
表の-n オプションの内容に関して、「デフォルトでは3です」 は、あえて入力しなくても3回は実行されるという意味です。-v オプションは付けておくことをお勧めします。ファイルサイズが大きくなったり、-n オプションで大きな値を設定したときは、画面がフリーズしたように見えて精神衛生上良くないですからね。
HDDなどからファイルを削除する場合、通常のゴミ箱に捨てて、ゴミ箱を空にするような方法では、実はほぼ全てのファイルが復元できてしまいます。ファイル復元ソフトによって、私自身、何度も救われたことがあるのですが、機密書類を削除したPCを手放すときには、復元されないか心配になります。そこで私は機密書類の処分にはこのような方法でデータを消しています。
しかし高度な磁気技術によって、特殊な技能を持つ人にしてみれば、このように悪あがきをしても内容を復元できてしまうようです[1]。ただ、一般人には不可能ですから、安心していいと思います笑。
ところが、聞くところによるとSSDほど高度な記録媒体になるとそもそも削除が難しいらしいです[1]。その場合は最初から暗号化しておけば良いとのことです。ということは SSD オンリーの Macbook を使っている私には、このコマンドはあまり意味がない...?
引用および更なる学習へ
[1] | データの完全消去 - Wikipedia | データを削除することに関する Wikipedia の記事です。グートマン方式(35回上書き)、国防総省方式など規格があることや、何ができるのかなどがわかります |
[2] | https://linuxjm.osdn.jp/html/GNU_coreutils/man1/shred.1.html | Linux での shred コマンドに関する解説です。GNU Coreutils で使えるものと同じはずです。 |