matplotlib は Python の可視化ライブラリの中で最も広く使われている定番です。pandas / NumPy のオブジェクトをそのまま描画できるため、分析の途中経過を素早くグラフにする手段として重要です。

本記事では、matplotlib の基本構造(Figure と Axes)を押さえた上で、折れ線・棒・ヒストグラムの 3 種類を株価データを題材に描きます。

目次

  1. インストール
  2. Figure と Axes の関係
  3. 折れ線:株価の推移
  4. 複数系列を重ねる
  5. 棒グラフ:出来高
  6. ヒストグラム:リターンの分布
  7. サブプロット:価格と出来高を同居させる
  8. 体裁のチェックリスト

インストール

Terminal window
pip install matplotlib pandas

検証バージョン: Python 3.12.5 / matplotlib 3.9.2 / pandas 2.2.3

Figure と Axes の関係

matplotlib のグラフは 2 階層で構成されます。

  • Figure: 紙の 1 枚に相当。サイズ・解像度・全体タイトルを持つ
  • Axes: 紙の上に置く描画領域(座標系を 1 つ持つ)。1 つの Figure に複数置ける

plt.subplots() で Figure と Axes を同時に作るのが現代的な書き方です。

import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot([1, 2, 3], [1, 4, 9])
ax.set_title("y = x^2")
plt.tight_layout()
plt.savefig("fig1.png", dpi=120)
plt.close(fig)

plt.tight_layout() でラベル類のはみ出しを防ぎ、plt.savefig で画像保存します。plt.show() は対話環境(Jupyter / IPython)で使い、ファイル化するなら savefig で十分です。

折れ線:株価の推移

最もよく使うのが折れ線(line plot)です。日付を x 軸、終値を y 軸に取ります。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
rng = np.random.default_rng(0)
dates = pd.date_range("2026-01-05", periods=100, freq="B")
close = pd.Series(2900 + rng.normal(0, 30, 100).cumsum(), index=dates, name="C")
fig, ax = plt.subplots(figsize=(10, 4))
ax.plot(close.index, close.values, color="C0", linewidth=1.4, label="7203 close")
ax.set_title("7203 close (synthetic)")
ax.set_xlabel("Date")
ax.set_ylabel("C (JPY)")
ax.grid(alpha=0.3)
ax.legend()
plt.tight_layout()
plt.savefig("close_line.png", dpi=120)
plt.close(fig)
株価終値の折れ線チャート

体裁のポイントは次の通りです。

  • color="C0" は標準色サイクルの 1 番目(濃い青)。別系列は "C1" "C2" と進める
  • linewidth は 1.4 程度が見やすい
  • grid(alpha=0.3) でうっすらしたグリッドを入れると、値の読み取りが楽になる
  • legend() を呼び出さないと凡例は表示されない

複数系列を重ねる

複数銘柄を同じ軸に重ねる場合は ax.plot を繰り返すだけです。

close_b = pd.Series(2900 + rng.normal(0, 25, 100).cumsum(), index=dates)
close_c = pd.Series(2900 + rng.normal(0, 35, 100).cumsum(), index=dates)
fig, ax = plt.subplots(figsize=(10, 4))
ax.plot(dates, close.values, label="A", color="C0")
ax.plot(dates, close_b.values, label="B", color="C1")
ax.plot(dates, close_c.values, label="C", color="C2")
ax.set_title("Three synthetic series")
ax.set_ylabel("C (JPY)")
ax.grid(alpha=0.3)
ax.legend(loc="upper left")
plt.tight_layout()
plt.savefig("multi_line.png", dpi=120)
plt.close(fig)

スケールが大きく違う 2 つの系列を重ねたい場合は、第 2 軸を作ります。

fig, ax1 = plt.subplots(figsize=(10, 4))
ax1.plot(dates, close.values, color="C0", label="close")
ax1.set_ylabel("C (JPY)")
ax2 = ax1.twinx()
volume = pd.Series(rng.integers(8_000_000, 15_000_000, 100), index=dates)
ax2.bar(dates, volume.values, alpha=0.2, color="gray", label="volume")
ax2.set_ylabel("Vo")
plt.tight_layout()
plt.savefig("dual_axis.png", dpi=120)
plt.close(fig)

第 2 軸の使いすぎは可読性を下げます。「価格と出来高」「価格と指標値」のように単位が明確に異なるときに限定するのが定石です。

棒グラフ:出来高

出来高は棒グラフ(bar plot)が定番です。

fig, ax = plt.subplots(figsize=(10, 3.5))
ax.bar(dates, volume.values, color="C0", width=0.8)
ax.set_title("Daily volume")
ax.set_ylabel("Vo")
ax.grid(axis="y", alpha=0.3)
plt.tight_layout()
plt.savefig("volume_bar.png", dpi=120)
plt.close(fig)
出来高の棒グラフ

grid(axis="y") で y 方向だけにグリッドを入れます。棒グラフは x 方向のグリッドが邪魔になりがちです。

ヒストグラム:リターンの分布

リターン(変化率)を見るときはヒストグラム(histogram)です。

returns = close.pct_change().dropna()
fig, ax = plt.subplots(figsize=(7, 4))
ax.hist(returns, bins=30, color="C0", edgecolor="white")
ax.set_title("Daily return distribution")
ax.set_xlabel("Return")
ax.set_ylabel("Frequency")
ax.axvline(0, color="black", linewidth=0.8)
ax.grid(alpha=0.3)
plt.tight_layout()
plt.savefig("return_hist.png", dpi=120)
plt.close(fig)
日次リターンの分布ヒストグラム

bins の数で見え方が変わります。少なすぎると粗く、多すぎるとガタつきます。データ件数が 100 程度なら 20 〜 30 が目安です。

axvline(0, ...) でゼロ位置に縦線を引くと、上昇日と下落日の偏りが分かりやすくなります。

サブプロット:価格と出来高を同居させる

plt.subplots に行・列を指定すると複数の Axes を作れます。価格と出来高を上下に並べる例です。

fig, (ax1, ax2) = plt.subplots(
2, 1, figsize=(10, 6),
sharex=True,
gridspec_kw={"height_ratios": [3, 1]},
)
ax1.plot(dates, close.values, color="C0")
ax1.set_ylabel("C")
ax1.grid(alpha=0.3)
ax2.bar(dates, volume.values, color="gray")
ax2.set_ylabel("Vo")
ax2.grid(axis="y", alpha=0.3)
fig.suptitle("Price and volume")
plt.tight_layout()
plt.savefig("price_volume.png", dpi=120)
plt.close(fig)

sharex=True で x 軸を共有し、height_ratios で上 3 : 下 1 の比率にしています。ローソク足チャートに近い見た目を作る基本パターンです。

体裁のチェックリスト

人に見せるチャートを作るときに見るべき項目をまとめます。

  • タイトル(set_title)があるか
  • 軸ラベル(set_xlabel / set_ylabel)があるか
  • 単位が分かるか(円・%・件数など)
  • 凡例(legend)が必要なのに省略していないか
  • 複数系列で色が衝突していないか(色覚のことも考慮)
  • 数値の桁が見にくいときに , 区切りにしてあるか

, 区切りは FuncFormatter で簡単に入れられます。

from matplotlib.ticker import FuncFormatter
fig, ax = plt.subplots(figsize=(8, 3))
ax.plot(dates, close.values * 100)
ax.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: f"{x:,.0f}"))
plt.tight_layout()
plt.savefig("formatted.png", dpi=120)
plt.close(fig)

生成AI へのプロンプト例

可視化は「描きたい絵」を具体的に書くと、出力ブレが減ります。

matplotlib で次のチャートを描くコードを書いてください。
入力:
- df(列: Date, C, sma_25, sma_75, Vo)
要件:
- 上下 2 段のサブプロット(高さ比 3:1)、x 軸を共有
- 上段: C を線、sma_25 / sma_75 を細線で重ねる、凡例付き
- 下段: Vo を棒グラフ、色は薄いグレー
- 画像は dpi=120 で chart.png に保存
- matplotlib 3.9 系、tight_layout を使用

「サブプロット構成」「線の種類」「色」「保存先」を順に書くと、再現性のあるコードが返ってきます。

まとめ

  • matplotlib は Figure(紙) と Axes(描画領域) の 2 層構造
  • 折れ線・棒・ヒストグラムの 3 種類で大半の用途は足りる
  • 複数系列・第 2 軸・サブプロットを組み合わせて情報量を上げられる
  • 体裁(タイトル・軸ラベル・凡例・グリッド)を欠かさないと、後で見返したときに意味が分かる