matplotlib
Pythonでグラフ画像を描くのに最も有名?
他のグラフ描画パッケージであるseabornや、pandasに付属するグラフ描画機能も、裏ではmatplotlibを用いている。
最近はJupyter Notebook上で、javascriptでぐりぐり動かせるグラフを描けるplotlyなども出てきてはいるけど、画像ならやはりこちらの方が多機能。
ただし、当然全てコマンド処理なので、少し凝ったことをしようとすると調べる手間が大きい。エクセルさんだとグラフを右クリックすると大抵何とかなるもんね。
Tips
日本語対応
デフォルトで使われるフォントが日本語入っていないため、タイトルや軸ラベルに日本語を使うと□になる。
日本語のフォントを使えばよい。OSにインストールされているTTF, OTFが使えるっぽい。
フォントの調べ方
import matplotlib.font_manager as fm fonts = fm.findSystemFonts() for f in fonts: fp = fm.FontProperties(fname=f) print(fp.get_name(), fp.get_family())
指定方法
上記の“fp.get_name()
“で判明したフォント名で指定する。
import matplotlib font = dict(family='Noto Sans CJK JP') matplotlib.rc('font', **font)
seabornを使うなら、こっちでもよい。
import seaborn as sns sns.set(font='Noto Sans CJK JP')
決まった位置にN数を出す
N数はデータの母数。
グラフには「総数がどれくらいか」は明記した方がよい。一見、結果が上手く出ているように見えても、実はN=10とかで何の説明力も無かった、なんてグラフを作ってはいけない。文章を併記するなら文章中に書いてもいいけど、せっかくグラフを描くなら、グラフだけ見ればわかるようにしたい。
matplotlibでは、テキストボックスで書くしか無い。ただし、以下の事情より、記述量が妙に多くなってしまう。
他の設定項目は、Text properties and layout — Matplotlib 2.0.2 documentation参照。
描画位置
描画位置をx,yで指定するが、これは「グラフ軸上の数値」であり、「グラフの枠内」での位置を指定しにくい。それには、transform=ax.transAxes
を指定すると、左下を起点とした0-1の数値を、グラフ軸上の数値に変換してくれる。
アンカー位置
デフォルトでは指定したx,yはテキストの左下に合わせられるので、右や上の端に表示する場合、はみ出てしまう。それには、ha(horizontalalignment)
とva(verticalalignment)
を指定し、右上に合わせるようにする。
枠
そのままではテキストが裸で表示される。枠を付ける場合、bbox
を指定する。bbox
には、設定を辞書形式で与える。とりあえずは、facecolor
とedgecolor
で色を指定するとよい。
import matplotlib.pyplot as plt plt.hist(任意のグラフ設定) # 描画領域を取得 ax = plt.gca() # テキストボックスを右上に描画 ax.text(0.95, 0.95, 'N={}'.format(len(data)), transform=ax.transAxes, ha='right', va='top', bbox=dict(facecolor='white', edgecolor='black'))
2軸目を使いつつ、凡例をまとめる
左右で別のy軸を使って2つのグラフをまとめて描画するには、第1軸目を使用するグラフを描いたaxオブジェクトからax.twinx()
を使用して第2軸目を使用するaxオブジェクトを生成し、そこに2つめのグラフを描く。
しかしその際、凡例を出すと、一方の凡例しか表示されない。 凡例はax内の要素に紐付くもので、1軸目と2軸目は別々に扱われるからのようだ。axから凡例情報を取得し、結合しないといけない。
import seaborn as sns d1 = [] # ←1次元データが入っているものとする d2 = [] # ←1次元データが入っているものとする # 最初の軸でグラフを描き、axオブジェクトを取得 ax1 = sns.distplot(d1, kde=False, label='ax1') # 2軸目を使うためのaxを作成 ax2 = ax1.twinx() # 2軸目でグラフを描く。'ax'引数で、描画するaxを指定できる sns.distplot(d2, kde=False, label='ax2', ax=ax2) # 凡例情報を取得する h1, l1 = ax1.get_legend_handles_labels() h2, l2 = ax2.get_legend_handles_labels() # 凡例情報を結合し、ax1の凡例として描画する ax1.legend(h1 + h2, l1 + l2) # 画像を保存 plt.savefig('graph/path.png') plt.close()