和風ましらに

機械学習とか勉強したことを書き認めるブログ

matplotlibのsubplotを使った図の作成

matplotlibの使い方、subplot関数の使い方についてまとめました

基本準備

Irisのデータを使う

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = sns.load_dataset("iris")

通常のグラフ作成

軸の範囲・表示値設定

  • xlim:x軸の値範囲
  • ylim:y軸の値範囲
  • xticks:表示するメモリの値

軸のテキスト設定

  • xlabel:x軸のラベル設定
  • ylabel:y軸のラベル設定
  • title:グラフのタイトル設定
plt.plot(df.sepal_width, df.sepal_length, '.', label="test")
plt.xlim(2.0,5.0)
plt.xticks([2,3,4, 5]) #メモリの設定
plt.yticks([4,5,6,7, 8])

plt.xlabel('sepal_width')# x軸のラベル設定
plt.ylabel('sepal_length')
plt.title('test',fontsize=20)

plt.legend(loc='best')# 一番いい感じのところで設定してくれる

f:id:nissyl:20190114105312p:plain
グラフの中のマーカーは、点以外にもたくさんある。 ここをみれば、いろいろ設定が乗っている https://jp.mathworks.com/help/matlab/creating_plots/create-line-plot-with-markers.html

重ねてグラフ表示

まずは普通に表示する

plt.plot(df.sepal_width, df.sepal_length,'.',color='red')
plt.plot(df.sepal_width, df.petal_length,'x',color='blue')

f:id:nissyl:20190114105641p:plain

だけど、違う種類同士のグラフだとy軸が重なり合って、良く分からない感じの図になる。

plt.hist(df.sepal_width , bins=20)
plt.plot(df.sepal_width, df.sepal_length,'.',color='red')

f:id:nissyl:20190114105822p:plain

解決策その1:別々のグラフにして表示する

まずfigureのインスタンスと言う箱的なのを作る。 その後、箱の中をサブプロットと言う関数で分けて、別々のグラフをその中で表示させる。 f:id:nissyl:20190114112128p:plain

fig = plt.figure(figsize=(8,8))

ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot((212), sharex=ax1)#y軸の共有

ax1.plot(df.sepal_width, df.sepal_length,'.',color='red')
ax2.hist(df.sepal_width , bins=20)

f:id:nissyl:20190114111430p:plain

解決策その2:グラフを上下に表示させる

ザックリとやってることをいかにまとめた。 f:id:nissyl:20190114112132p:plain

fig = plt.figure(figsize=(6,6))

# サブプロットを8:2で分割
ax1 = fig.add_axes((0, 0.2, 1, 0.8))#[left(左端からの距離), bottom(下からの距離), width(幅), height(高さ)]
ax2 = fig.add_axes((0, 0, 1, 0.2), sharex=ax1)

# 散布図のx軸のラベルとヒストグラムのy軸のラベルを非表示
ax1.tick_params(labelbottom="off")

#ラベル設定
ax1.set_ylabel('sepal_length')
ax2.set_ylabel('count')

ax1.plot(df.sepal_width, df.sepal_length,'.',color='red')
ax2.hist(df.sepal_width , bins=20)

f:id:nissyl:20190114110856p:plain

参考資料
http://bicycle1885.hatenablog.com/entry/2014/02/14/023734

解決策その3:左右のy軸で別々の値を表示させる

Figureのインスタンスを生成し、Axesのインスタンスの中でx軸を共有させてグラフを作るといい感じに作れる。(twinx()関数)
詳しくは後でまとめるので、一旦コードだけ。

fig = plt.figure(figsize=(6,6))

# サブプロットを作成・x軸の共有
ax1 = fig.add_subplot(111)
ax2 = ax1.twinx()

#ラベル設定
ax1.set_xlabel('sepal_width')
ax1.set_ylabel('sepal_length')
ax2.set_ylabel('count')

ax1.plot(df.sepal_width, df.sepal_length,'.',color='red')
ax2.hist(df.sepal_width , bins=20,alpha=0.4)

f:id:nissyl:20190114110939p:plain

補足

  • legendについて
    legendを表示させる場合は、普通にやると上手くいかない。
    なので、以下のようにして一つにまとめてやる必要がある。
handler1, label1 = ax1.get_legend_handles_labels()
handler2, label2 = ax2.get_legend_handles_labels()
ax1.legend(handler1 + handler2, label1 + label2, loc='best',fontsize=14)
  • axesでのx軸目盛について
    こちらも普通にax1.xtickとかやっても上手くいかない。
    ax1.set_xticklabels([~~], rotation = 90)とかで処理できる