LoginSignup
35
39

More than 3 years have passed since last update.

Matplotlib でグラフの書き方メモ (折れ線グラフ・棒グラフ・ヒストグラム・散布図編・箱ひげ図)

Last updated at Posted at 2018-03-10

概要

matplotlib でグラフを書く場合、方法が複数種類かあり、それぞれ使うメソッドが少しずつ違ってよく混乱するので、とりあえずこれみてコピペすればうまくいくメモを作る。

記述パターン

記述のパターン名称を、ここでは下記のように呼ぶ。

  • dfパターン: DataFrameplot()plot.bar() メソッド等を使ってグラフを書く方法。グラフを適した形に df を作る必要はあるが、ax の操作をラップしてくれているので、だいたいにおいてもっとも簡単。
  • axパターン: axplot()bar() メソッド等を使ってグラフを書く方法。 DataFrame を使わない場合や構造変更が大変な場合などはこちらを使う。

pltplot()bar() メソッド等を使って書く Pyplotインターフェイス もあるが推奨されていないので紹介は省く。

import

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

参考ドキュメント

折れ線グラフ

image.png

# データ
df = pd.DataFrame({'x': [10, 20, 30], 'a': [100, 300, 200], 'b': [300, 100, 250]})

# dfパターン
fig, ax = plt.subplots(figsize=(5, 2))
df.set_index('x').plot(  # indexがx軸に。各columnが各線に。
    ax=ax,
    #legend=False,  # 凡例OFF
)
ax.set_title('タイトル')
#ax.set_xlabel('')  # xラベルOFF
ax.set_ylabel('y')
plt.show()

# axパターン
fig, ax = plt.subplots(figsize=(5, 2))
ax.plot(df.x, df.a)
ax.plot(df.x, df.b)
ax.legend()  # 凡例ON
ax.set_title('タイトル')
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()

# これは警告でるのでNG
# y の複数指定に対応していない?
# df.plot(x='x',y=['a', 'b'], figsize=(10, 2), title='df + xy明示')

積層折れ線グラフ

image.png

# 値にマイナスがあると積層グラフ出せないので注意
df = pd.DataFrame({'x': [10, 20, 30], 'a': [100, 300, 200], 'b': [300, 100, 250]})

# dfパターン
fig, ax = plt.subplots(figsize=(5, 2))
df.set_index('x').plot.area(  # indexがx軸に。各columnが各線に。
    ax=ax,
    stacked=True,  # 積み上げ
    #legend=False,  # 凡例OFF
)
ax.set_title('タイトル')
#ax.set_xlabel('')  # xラベルOFF
ax.set_ylabel('y')
plt.show()

棒グラフ

image.png

df = pd.DataFrame({'x': ['A', 'B', 'C'], 'a': [100, 300, 200], 'b': [300, -100, 250]})

# dfパターン
fig, ax = plt.subplots(figsize=(5, 2))
df.set_index('x').plot.bar(  # indexがx軸に。各columnが各線に。
    ax=ax,
    rot=True,  # 指定しない場合、ラベルが横倒しになる
    #legend=False,  # 凡例OFF
)
ax.set_title('タイトル')
# ax.set_xlabel('')  # x軸ラベルOFF
ax.set_ylabel('y')
ax.axhline(y=0, color='silver', linestyle='-', linewidth=1)  # 0に補助線
plt.show()

# axパターン
w = 0.3  # 棒の太さ
fig, ax = plt.subplots(figsize=(5, 2))
ax.bar(df.x.index    , df.a, width=w, label='a')
ax.bar(df.x.index + w, df.b, width=w, label='b')
ax.set_xticks(df.x.index + w / 2)
ax.set_xticklabels(df.x)
# rotation=90 で x ラベルが横倒しになる
ax.legend()  # 凡例ON
ax.set_title('タイトル')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.axhline(y=0, color='silver', linestyle='-', linewidth=1)  # 0に補助線
plt.show()

棒グラフ(横)

image.png

df = pd.DataFrame({'z': ['A', 'B', 'C'], 'a': [100, 300, 200], 'b': [300, -100, 250]})

# dfパターン
# A→B→C の順に上から並べたいなら逆順にしておく必要がある。デフォルトは下から並ぶので。
fig, ax = plt.subplots(figsize=(5, 2))
df.set_index('z').plot.barh(  # indexがx軸に。各columnが各線に。
    ax=ax,
    #legend=False,  # 凡例OFF
)
ax.set_title('タイトル')
ax.set_xlabel('x')
# ax.set_ylabel('')  # y軸ラベルOFF
ax.axvline(x=0, color='silver', linestyle='-', linewidth=1)  # 0に補助線
plt.show()

# axパターン
w = 0.3  # 棒の太さ
fig, ax = plt.subplots(figsize=(5, 2))
ax.barh(df.z.index    , df.a, height=w, label='a')
ax.barh(df.z.index + w, df.b, height=w, label='b')
ax.set_yticks(df.z.index + w / 2)
ax.set_yticklabels(df.z)
ax.legend()  # 凡例ON
ax.set_title('タイトル')
ax.set_xlabel('x')
ax.set_ylabel('z')
ax.axvline(x=0, color='silver', linestyle='-', linewidth=1)  # 0に補助線
plt.show()

積み上げ棒グラフ

image.png

# 注意:値にマイナスが含まれていると予期しないグラフになる可能性あり
df = pd.DataFrame({'x': ['A', 'B', 'C'], 'a': [100, 300, 200], 'b': [300, 100, 250]})

# dfパターン(これが一番簡単)
fig, ax = plt.subplots(figsize=(5, 2))
df.set_index('x').plot.bar(  # indexがx軸に。各columnが各線に。
    ax=ax,
    stacked=True,  # 積み上げ
    rot=0,  # xticks ラベルの角度。指定しない場合、ラベルが横倒しになる
    legend='reverse', #, legend=False で凡例OFF
)
ax.set_title('タイトル')
# ax.set_xlabel('')  # x軸ラベルOFF
ax.set_ylabel('y')
plt.show()

# axパターン
# ※ dfパターンを使うべき
# fig, ax = plt.subplots(figsize=(5, 2))
# ax.bar(df.x, df.a + df.b, label='b')  # 上の段から順に書いていく
# ax.bar(df.x, df.a,        label='a')  # 重ねて書いていく
# # rotation=90 で x ラベルが横倒しになる
# ax.legend()  # 凡例ON
# ax.set_title('タイトル')
# ax.set_xlabel('x')
# ax.set_ylabel('y')
# plt.show()

ヒストグラム

image.png

df = pd.DataFrame(np.random.normal(0, 100, (50, 3)), columns=['a', 'b', 'c'])

# dfパターン(これが一番簡単)
fig, ax = plt.subplots(figsize=(5, 2))
df.a.plot.hist(
    ax=ax,
    bins=10,  # 何等分するか
)
ax.legend()
ax.set_title('タイトル')
ax.set_xlabel('a')
ax.set_ylabel('')  # y軸ラベルOFF
plt.show()

# axパターン
fig, ax = plt.subplots(figsize=(5, 2))
ax.hist(df.a, bins=10)
ax.legend()  # 凡例ON
ax.set_title('タイトル')
ax.set_xlabel('a')
#ax.set_ylabel('出現回数')
plt.show()

ヒストグラム(複数並べる)

image.png

df = pd.DataFrame(np.random.normal(0, 100, (50, 3)), columns=['a', 'b', 'c'])

# dfパターン
axes = df.plot.hist(
    bins=10,  # 何等分するか
    figsize=(10, 3),
    subplots=True,  # 列ごとにグラフを分ける
    layout=(1, 3),  # 表の並びを指定 (rows, cols)
    sharex=True,  # x軸のmin/maxを共有したい場合にTrue 。その場合、ラベルは右端と左端の表だけに表示される
    sharey=True,  # y軸のmin/maxを共有したい場合にTrue 。その場合、ラベルは右端と左端の表だけに表示される
)
fig = plt.gcf()
fig.suptitle('タイトル')
for i, c in enumerate(['a', 'b', 'c']):
    axes[0, i].set_xlabel(c)
axes[0, 0].set_ylabel('')
plt.show()

# axパターン
fig, axes = plt.subplots(1, 3, sharex=True, sharey=True, figsize=(10, 3))  # 縦 x 横 の 何番目。
for i, c in enumerate(['a', 'b', 'c']):
    axes[i].hist(df[c], bins=10, color=f"C{i}")
    axes[i].set_xlabel(c)
    axes[i].legend()
fig = plt.gcf()
fig.suptitle('タイトル')
plt.show()

散布図

image.png

df = pd.DataFrame(np.random.normal(0, 100, (1000, 3)), columns=['a', 'b', 'c'])

# dfパターン
fig, ax = plt.subplots(figsize=(5, 2))
df.plot.scatter(ax=ax, x='a', y='b', c='C0', alpha=0.2, label='b')
df.plot.scatter(ax=ax, x='a', y='c', c='C1', alpha=0.2, label='c')
# それぞれに legend=False を加えることで凡例OFF
ax.set_title('タイトル')
# ax.set_xlabel('')  # x軸ラベルOFF
# ax.set_ylabel('')  # y軸ラベルOFF
plt.show()

# axパターン
fig, ax = plt.subplots(figsize=(5, 2))
ax.scatter(x=df.a, y=df.b, alpha=0.2, label='b')
ax.scatter(x=df.a, y=df.c, alpha=0.2, label='c')
ax.legend()
ax.set_title('タイトル')
ax.set_xlabel('b')
ax.set_ylabel('c')
plt.show()

箱ひげ図

image.png

df = pd.DataFrame(np.random.normal(0, 100, (1000, 3)), columns=['a', 'b', 'c'])

# dfパターン
fig, ax = plt.subplots(figsize=(5, 2))
df.boxplot(ax=ax, column=['a', 'b', 'c'])
ax.set_title('タイトル')
plt.show()

image.png

df = pd.DataFrame({
    'a': np.random.normal(0, 10, 1000),
    'b': np.random.randint(0, 10, 1000),
})

# dfパターン
fig, ax = plt.subplots(figsize=(5, 2))
df.boxplot(ax=ax, column=['a'], by=['b'])
ax.set_title('')
ax.set_ylabel('a')
ax.set_xlabel('b')
plt.show()

xTicksラベルの表示を変更

image.png

df = pd.DataFrame({'x': [10, 20, 40], 'a': [100, 300, 200]})

fig, ((ax1, ax2, ax3)) = plt.subplots(1, 3, figsize=(15, 1))
fig.subplots_adjust(wspace=0.4, hspace=1.5)  # 横 縦 のグラフの間

df.set_index('x').plot(ax=ax1, title='1. デフォルト')

df.set_index('x').plot(ax=ax2, title='2. 固定値で表示')
ax2.xaxis.set_major_locator(ticker.FixedLocator(df.x))
ax2.xaxis.set_major_formatter(ticker.FixedFormatter(df.x))  # x軸のTicksを固定値に

df.set_index('x').plot(ax=ax3, title='3. 一定間隔 + Formatter')
ax3.xaxis.set_major_locator(ticker.MultipleLocator(10))
ax3.xaxis.set_major_formatter(ticker.FormatStrFormatter('%1.1f'))  # x軸のTicksを固定値に

plt.show()

参考:

x 軸目盛りの代わりにテーブル表示

image.png

df = pd.DataFrame({'x': [10, 20, 30], 'a': [100, 300, 200], 'b': [300, 100, 250]})
fig, ax = plt.subplots(figsize=(5, 2))
df.set_index('x').plot(  # indexがx軸に。各columnが各線に。
    ax=ax,
    table=True,  # テーブル表示
    xticks=[],  # 目盛り非表示
)
ax.set_xlabel('')
plt.show()

グラフを横に並べる

image.png

# axパターン
df = pd.DataFrame([100, 300, 200])
fig = plt.figure(figsize=(10, 2))  # 全体枠の大きさ (w, h) inch
fig.subplots_adjust(wspace=0.4, hspace=1.5)  # 横 縦 のグラフの間
for i in [1, 2, 3, 4, 5]:
    ax = fig.add_subplot(2, 3, i)
    df.plot(title=f"グラフ{i}", ax=ax)
plt.show()

image.png

# dfパターン(列ごとにグラフを分割する用)
df = pd.DataFrame({'x': [10, 20, 30], 'a': [100, 300, 200], 'b': [200, 100, 250], 'c': [200, 100, 250]})
df.set_index('x').plot(
    title='タイトル',
    figsize=(10, 2), # 全体枠の大きさ (w, h) inch
    rot=0,  # xticksラベルの角度。指定しない場合、ラベルが斜めになる
    subplots=True,  # 列ごとにグラフを分ける
    layout=(2, 2),  # 表の並びを指定 (rows, cols)
    sharex=True,  # x軸のmin/maxを共有したい場合にTrue 。その場合、ラベルは右端と左端の表だけに表示される
    sharey=True,  # y軸のmin/maxを共有したい場合にTrue 。その場合、ラベルは右端と左端の表だけに表示される
)
plt.show()
35
39
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
39