Matplotlib実践Tips:論文品質のグラフを作る

Matplotlibで論文品質のグラフを作成するためのTipsを紹介します。rcParams設定、日本語フォント、カラーマップ選択、ベクター出力まで実践的に解説します。

はじめに

Matplotlibはデフォルト設定のまま使うと、フォントサイズが小さかったり、線が細すぎたり、論文やプレゼンテーションに直接使うには不十分なグラフが出力されます。設定を調整することで、そのまま論文に載せられる品質のグラフを作成できます。

この記事では、論文品質のグラフを作成するための実践的なTipsを紹介します。

rcParamsによるグローバル設定

plt.rcParamsを使うと、スクリプト全体のデフォルトスタイルを一括で変更できます。以下のテンプレートを使えば、毎回個別に設定する必要がなくなります。

import matplotlib.pyplot as plt

plt.rcParams.update({
    'font.size': 12,
    'axes.labelsize': 14,
    'axes.titlesize': 14,
    'xtick.labelsize': 11,
    'ytick.labelsize': 11,
    'legend.fontsize': 11,
    'figure.figsize': (6, 4),
    'figure.dpi': 150,
    'lines.linewidth': 1.5,
    'axes.linewidth': 0.8,
    'axes.grid': True,
    'grid.alpha': 0.3,
})

各パラメータの説明

  • font.size: 基本フォントサイズ。ここを基準に他のサイズも調整されます
  • axes.labelsize, axes.titlesize: 軸ラベルとタイトルのサイズ。本文より少し大きくすると読みやすくなります
  • figure.figsize: デフォルトの図サイズ(インチ単位)。論文のカラム幅に合わせて調整します
  • figure.dpi: 解像度。150以上にしておくとノートブック上でも鮮明に表示されます
  • axes.grid, grid.alpha: 薄いグリッド線を表示してデータの読み取りを助けます

デフォルト設定 vs カスタム設定

スタイルシートとの併用

Matplotlibにはプリセットのスタイルシートもあります。rcParamsと併用する場合、スタイルシートを先に適用してから個別に上書きします。

plt.style.use('seaborn-v0_8-whitegrid')
plt.rcParams.update({
    'font.size': 12,
    'axes.labelsize': 14,
})

日本語フォントの設定

Matplotlibはデフォルトでは日本語フォントに対応しておらず、そのままでは文字化けします。

macOSの場合

macOSではjapanize-matplotlibパッケージを使うのが最も簡単です。

pip install japanize-matplotlib
import matplotlib.pyplot as plt
import japanize_matplotlib

plt.plot([1, 2, 3], [1, 4, 9])
plt.title("日本語タイトル")
plt.xlabel("X軸ラベル")
plt.ylabel("Y軸ラベル")
plt.show()

手動でフォントを指定する方法

japanize-matplotlibを使わない場合、フォントパスを直接指定できます。

import matplotlib
from matplotlib import font_manager

# macOS
font_path = '/System/Library/Fonts/ヒラギノ角ゴシック W3.ttc'
# Linux
# font_path = '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc'

font_manager.fontManager.addfont(font_path)
matplotlib.rc('font', family='Hiragino Sans')

Linuxの場合

Linux環境ではNotoフォントなどをインストールしてから設定します。

# フォント一覧の確認
fc-list :lang=ja

# Noto Sans CJKのインストール(Ubuntu/Debian)
sudo apt install fonts-noto-cjk

フォントキャッシュのクリアが必要な場合があります。

import matplotlib
matplotlib.font_manager._load_fontmanager(try_read_cache=False)

カラーマップの選択

jet/rainbowを避ける理由

jetrainbowは色覚多様性のある読者にとって判読が困難です。また、明るさが均一でないため、データの大小関係が正しく伝わらない場合があります。

推奨カラーマップ

連続データには以下のカラーマップが推奨されます。

  • viridis: デフォルトカラーマップ。明るさが均一で色覚多様性に配慮されています
  • cividis: viridisに似ていますが、より色覚バリアフリーに特化しています
  • plasma: 暖色系で、viridisとの使い分けに適しています
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 10, 100)
y = np.linspace(0, 10, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(X) * np.cos(Y)

fig, axes = plt.subplots(1, 3, figsize=(15, 4))
cmaps = ['viridis', 'cividis', 'plasma']

for ax, cmap in zip(axes, cmaps):
    im = ax.pcolormesh(X, Y, Z, cmap=cmap)
    ax.set_title(cmap)
    fig.colorbar(im, ax=ax)

plt.tight_layout()
plt.show()

カラーマップの比較

カテゴリデータ用の定性パレット

カテゴリデータ(折れ線グラフで複数系列を区別する場合など)には定性パレットを使います。

# tab10: 最大10色、区別しやすい配色
colors = plt.cm.tab10.colors

for i in range(5):
    plt.plot(x, np.sin(x + i), color=colors[i], label=f'Series {i+1}')

plt.legend()
plt.show()

Set2Dark2も論文向きの落ち着いた色合いで使いやすいパレットです。

サブプロットの配置と軸の共有

基本的なサブプロット

fig, axes = plt.subplots(2, 2, figsize=(10, 8), sharex=True, sharey=True)

for ax in axes.flat:
    ax.plot(np.random.randn(50).cumsum())

fig.align_ylabels(axes[:, 0])
plt.tight_layout()
plt.show()

sharex=Truesharey=Trueを指定すると、各サブプロットで軸の範囲が統一されます。fig.align_ylabels()でy軸ラベルの位置も揃えられます。

gridspec_kwによる細かいレイアウト制御

サブプロット間の余白を調整したい場合はgridspec_kwを使います。

fig, axes = plt.subplots(
    2, 2,
    figsize=(10, 8),
    gridspec_kw={'hspace': 0.05, 'wspace': 0.05},
    sharex=True,
    sharey=True
)

サイズの異なるサブプロット

GridSpecを使うと、サブプロットごとに異なるサイズを指定できます。

from matplotlib.gridspec import GridSpec

fig = plt.figure(figsize=(10, 6))
gs = GridSpec(2, 3, figure=fig)

ax_main = fig.add_subplot(gs[:, :2])   # 左側2/3を占める大きなプロット
ax_top = fig.add_subplot(gs[0, 2])     # 右上
ax_bottom = fig.add_subplot(gs[1, 2])  # 右下

ベクター出力(PDF/SVG)

ベクター形式で保存する

論文投稿にはベクター形式(PDF, SVG)が推奨されます。拡大しても画質が劣化しません。

fig, ax = plt.subplots()
ax.plot([1, 2, 3], [1, 4, 9])

# PDF出力
fig.savefig('figure.pdf', bbox_inches='tight')

# SVG出力
fig.savefig('figure.svg', bbox_inches='tight')

bbox_inches='tight'を指定すると、余白が自動的にトリミングされます。

ラスター形式を使う場面

以下のような場合はPNG(ラスター形式)の方が適しています。

  • データ点が非常に多い散布図(数万点以上)
  • ヒートマップやイメージプロット
  • ファイルサイズを小さくしたい場合

ラスター形式で保存する場合はdpiを指定します。

fig.savefig('figure.png', dpi=300, bbox_inches='tight')

ベクターとラスターの組み合わせ

一つの図の中でベクターとラスターを混在させることもできます。rasterized=Trueを指定した要素だけがラスター化されます。

ax.scatter(x, y, rasterized=True)  # 散布図だけラスター化
fig.savefig('figure.pdf', dpi=300, bbox_inches='tight')

完成例:すべてのTipsを組み合わせる

以下は、ここまで紹介したTipsをすべて組み合わせた完成例です。

import numpy as np
import matplotlib.pyplot as plt

# グローバル設定
plt.rcParams.update({
    'font.size': 12,
    'axes.labelsize': 14,
    'axes.titlesize': 14,
    'xtick.labelsize': 11,
    'ytick.labelsize': 11,
    'legend.fontsize': 11,
    'figure.figsize': (6, 4),
    'figure.dpi': 150,
    'lines.linewidth': 1.5,
    'axes.linewidth': 0.8,
    'axes.grid': True,
    'grid.alpha': 0.3,
})

# データ生成
np.random.seed(42)
x = np.linspace(0, 2 * np.pi, 100)
signals = {
    'Signal A': np.sin(x) + np.random.normal(0, 0.1, 100),
    'Signal B': np.cos(x) + np.random.normal(0, 0.1, 100),
    'Signal C': np.sin(2 * x) + np.random.normal(0, 0.1, 100),
}

# カテゴリ用パレット
colors = plt.cm.Set2.colors

# サブプロット作成
fig, axes = plt.subplots(1, 2, figsize=(12, 4.5))

# 左: 折れ線グラフ
ax = axes[0]
for i, (label, data) in enumerate(signals.items()):
    ax.plot(x, data, color=colors[i], label=label)
ax.set_xlabel('Time [s]')
ax.set_ylabel('Amplitude')
ax.set_title('Time Series Comparison')
ax.legend()

# 右: ヒートマップ
ax = axes[1]
X, Y = np.meshgrid(x, x)
Z = np.sin(X) * np.cos(Y)
im = ax.pcolormesh(X, Y, Z, cmap='cividis', rasterized=True)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('2D Heatmap')
fig.colorbar(im, ax=ax)

plt.tight_layout()

# ベクター形式で保存
fig.savefig('publication_figure.pdf', bbox_inches='tight')
fig.savefig('publication_figure.svg', bbox_inches='tight')
plt.show()

完成例:論文品質のグラフ

まとめ

論文品質のグラフを作成するためのポイントをまとめます。

  • rcParamsでグローバル設定を定義し、一貫したスタイルを維持する
  • 日本語フォントはjapanize-matplotlibで手軽に対応する
  • カラーマップは色覚多様性に配慮したviridis系を選ぶ
  • サブプロットはsharex/shareyalign_ylabelsで整列させる
  • 最終出力はPDF/SVGのベクター形式で保存する

Matplotlibの基本的な使い方や3Dアニメーション(GIF)の作成方法については、MatplotlibでGIFアニメーションを作成する方法もご参照ください。