Matplotlibのカラーマップ:Pythonにおけるカラーマップ完全ガイド
Updated on
データ可視化で適切な色を選ぶのは、見た目以上に難しい作業です。虹色のカラーマップを選べばヒートマップは派手に見えますが、知覚的に一様ではないためデータが歪んで見え、閲覧者を誤解させ、色覚特性のある人にはまったく機能しないこともあります。単一色相のパレットを使うと、微妙なパターンがほぼ同じ濃淡の壁に埋もれてしまいます。洞察を引き出すグラフと、洞察を隠してしまうグラフの差は、しばしばたった1つの判断――カラーマップ――で決まります。
Matplotlibには150以上の組み込みカラーマップと、自作できる柔軟なAPIが用意されています。問題は選択肢が少ないことではなく、「どのカラーマップを、いつ使い、データセットに合わせてどうカスタマイズするか」を知ることです。選択を誤ると可視化の正確性を静かに壊してしまい、正しい選択をすれば複雑なデータも一目で読めるようになります。
このガイドでは、Matplotlibのカラーマップに関する実用的な要点をすべて扱います。4つの主要カテゴリ、重要な組み込みマップ、プロット種類ごとの適用方法、ゼロからのカスタムカラーマップ作成、そして科学的に正確でアクセシブルなカラーマップの選び方まで解説します。
Matplotlibにおけるカラーマップとは?
カラーマップは、スカラーのデータ値を色に変換するための対応付け(マッピング)関数です。数値(通常は0〜1に正規化された値)を与えると、カラーマップはRGBAの色タプルを返します。Matplotlibでは、カラーマップは matplotlib.colors.Colormap を継承するオブジェクトとして表現され、cmap パラメータを受け取るすべての描画関数は内部でこの仕組みを使っています。
import matplotlib.pyplot as plt
import numpy as np
# A colormap is a callable: pass a float in [0, 1], get an RGBA tuple
cmap = plt.colormaps['viridis']
print(cmap(0.0)) # dark purple
print(cmap(0.5)) # teal-green
print(cmap(1.0)) # bright yellowplt.imshow(data, cmap='viridis') のように書くと、Matplotlibはまず Normalize オブジェクトでデータを[0, 1]に正規化し、その正規化値をカラーマップに通して最終的なピクセル色を得ます。この「正規化 → 色の参照」という2段階プロセスを理解することが、プロットの色を思い通りに制御する鍵です。
カラーマップの4つのカテゴリ
Matplotlibはカラーマップを4つの機能カテゴリに整理しています。それぞれが異なる種類のデータに対応しており、間違ったカテゴリを選ぶことが最もよくあるカラーマップのミスです。
逐次(Sequential)カラーマップ
逐次カラーマップは、単一の色相または狭い色相範囲の中で、明→暗(あるいは暗→明)へ滑らかに変化します。特別な中点を持たず、低→高という自然な順序を持つデータ向けに設計されています。
使いどき: 気温、人口密度、標高、確率など、低い値から高い値へ意味のある方向性を持つ連続変数。
代表例: viridis, plasma, inferno, magma, cividis, Blues, Greens, OrRd, YlGnBu
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(12, 12)
fig, axes = plt.subplots(1, 3, figsize=(14, 4))
for ax, name in zip(axes, ['viridis', 'plasma', 'inferno']):
im = ax.imshow(data, cmap=name)
ax.set_title(f'Sequential: {name}')
fig.colorbar(im, ax=ax, shrink=0.8)
plt.tight_layout()
plt.show()発散(Diverging)カラーマップ
発散カラーマップは、対照的な2つの色相が中立的な中点(通常は白や薄い灰色)で合流する構成です。中心値からの正負(両方向)の偏差を強調します。
使いどき: 平均からの偏差(平年差など)、相関行列、損益、0や基準点が特別な意味を持つデータ。
代表例: coolwarm, RdBu, RdYlGn, BrBG, PiYG, seismic, bwr
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
data = np.random.randn(10, 10) # Values centered around zero
fig, axes = plt.subplots(1, 3, figsize=(14, 4))
for ax, name in zip(axes, ['coolwarm', 'RdBu', 'seismic']):
im = ax.imshow(data, cmap=name, vmin=-3, vmax=3)
ax.set_title(f'Diverging: {name}')
fig.colorbar(im, ax=ax, shrink=0.8)
plt.tight_layout()
plt.show()Tip: vmin と vmax は必ず中点に対して対称に設定し、中立色が0(または選んだ中心値)に揃うようにしましょう。
定性(Qualitative)カラーマップ
定性カラーマップは順序の含意がない、視覚的に区別しやすい色のセットを提供します。隣り合う色同士ができるだけ異なるように設計されており、カテゴリラベルに最適です。
使いどき: クラスタラベル、カテゴリの散布図、順序のないグループを持つ棒グラフ。
代表例: tab10, tab20, Set1, Set2, Set3, Paired, Accent
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(7)
categories = 6
x = np.concatenate([np.random.randn(30) + i * 3 for i in range(categories)])
y = np.concatenate([np.random.randn(30) + i * 1.5 for i in range(categories)])
labels = np.concatenate([np.full(30, i) for i in range(categories)])
plt.figure(figsize=(9, 6))
scatter = plt.scatter(x, y, c=labels, cmap='tab10', s=50, alpha=0.8, edgecolors='white')
plt.colorbar(scatter, label='Category')
plt.title('Qualitative Colormap: tab10')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()周期(Cyclic)カラーマップ
周期カラーマップは開始色と終了色が同じで、周回するデータ(角度、位相、時刻、風向など)に適しています。
使いどき: 位相データ、方位、周期信号、時刻(0時と24時が同じ意味を持つなど)。
代表例: twilight, twilight_shifted, hsv
import matplotlib.pyplot as plt
import numpy as np
theta = np.linspace(0, 2 * np.pi, 300)
r = np.linspace(0, 1, 300)
T, R = np.meshgrid(theta, r)
Z = T # Color represents angle
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'}, figsize=(6, 6))
im = ax.pcolormesh(T, R, Z, cmap='twilight', shading='auto')
fig.colorbar(im, ax=ax, label='Angle (radians)')
ax.set_title('Cyclic Colormap: twilight')
plt.show()比較表:カラーマップカテゴリ
| Category | Purpose | Midpoint Matters? | Ordering? | Best For | Examples |
|---|---|---|---|---|---|
| Sequential | 低→高の値 | No | Yes | 密度、温度、カウント | viridis, plasma, inferno, Blues |
| Diverging | 中心からの偏差 | Yes | Yes (both directions) | 異常値、相関、損益 | coolwarm, RdBu, BrBG |
| Qualitative | 区別可能なカテゴリ | No | No | ラベル、クラスタ、グループ | tab10, Set1, Paired |
| Cyclic | 周回するデータ | No | Circular | 位相、角度、時刻 | twilight, hsv |
組み込みカラーマップ リファレンス
Matplotlibには複数のファミリに属するカラーマップが含まれています。ここではカテゴリ別に、特によく使われるものをまとめます。
知覚的に一様な逐次(Perceptually Uniform Sequential)
これらは、データ上の等間隔のステップが、知覚上の明るさの等間隔として感じられるよう設計されています。多くのケースでデフォルト推奨です。
| Colormap | Description | Colorblind Safe |
|---|---|---|
viridis | 紫→黄、Matplotlib 2.0以降のデフォルト | Yes |
plasma | 紫→黄でコントラスト高め | Yes |
inferno | 黒→赤→黄を経由 | Yes |
magma | 黒→紫/ピンク→白 | Yes |
cividis | 青→黄、色覚特性を考慮して最適化 | Yes |
人気の発散カラーマップ
| Colormap | Description | Colorblind Safe |
|---|---|---|
coolwarm | 青→赤、滑らかな遷移 | Partially |
RdBu | 赤→青、コントラスト強め | No |
RdYlGn | 赤→黄→緑 | No |
BrBG | 茶→青緑 | Partially |
PiYG | ピンク→緑 | Partially |
seismic | 青→赤、彩度強め | No |
プロット種類ごとのカラーマップ利用
imshowによるヒートマップ
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
data = np.random.rand(8, 10)
fig, ax = plt.subplots(figsize=(10, 6))
im = ax.imshow(data, cmap='YlOrRd', aspect='auto')
ax.set_xlabel('Columns')
ax.set_ylabel('Rows')
ax.set_title('Heatmap with YlOrRd Colormap')
fig.colorbar(im, ax=ax, label='Value')
plt.tight_layout()
plt.show()色で値を表現する散布図
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
n = 300
x = np.random.randn(n)
y = np.random.randn(n)
distance = np.sqrt(x**2 + y**2)
plt.figure(figsize=(8, 6))
sc = plt.scatter(x, y, c=distance, cmap='magma', s=40, alpha=0.8, edgecolors='gray', linewidths=0.3)
plt.colorbar(sc, label='Distance from Origin')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Scatter Plot with magma Colormap')
plt.show()等高線プロット
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3, 3, 200)
y = np.linspace(-3, 3, 200)
X, Y = np.meshgrid(x, y)
Z = np.sin(X) * np.cos(Y)
fig, axes = plt.subplots(1, 2, figsize=(13, 5))
# Filled contour
cf = axes[0].contourf(X, Y, Z, levels=20, cmap='RdBu')
fig.colorbar(cf, ax=axes[0])
axes[0].set_title('contourf with RdBu')
# Line contour with colormap
cl = axes[1].contour(X, Y, Z, levels=15, cmap='plasma')
axes[1].clabel(cl, inline=True, fontsize=8)
axes[1].set_title('contour with plasma')
plt.tight_layout()
plt.show()不規則グリッド向けのpcolormesh
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(0)
x = np.linspace(0, 4, 50)
y = np.linspace(0, 3, 40)
X, Y = np.meshgrid(x, y)
Z = np.exp(-(X - 2)**2 - (Y - 1.5)**2) + 0.5 * np.sin(3 * X) * np.cos(3 * Y)
plt.figure(figsize=(9, 6))
pcm = plt.pcolormesh(X, Y, Z, cmap='cividis', shading='auto')
plt.colorbar(pcm, label='Intensity')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('pcolormesh with cividis Colormap')
plt.tight_layout()
plt.show()カラーバーのカスタマイズ
カラーバーはカラーマップの凡例です。適切にカスタマイズすることは、読みやすい可視化に不可欠です。
基本的なカラーバー設定
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(10, 10)
fig, ax = plt.subplots(figsize=(8, 6))
im = ax.imshow(data, cmap='viridis')
cbar = fig.colorbar(im, ax=ax, orientation='vertical', shrink=0.8, pad=0.02)
cbar.set_label('Measurement Value', fontsize=12)
cbar.ax.tick_params(labelsize=10)
plt.title('Colorbar Customization')
plt.tight_layout()
plt.show()BoundaryNormによる離散カラーバー
データが自然に離散的なビン(リスクレベル、評価カテゴリなど)に分かれる場合、BoundaryNorm を使うと、滑らかなグラデーションではなく明確な境界を持つ色分けにできます。
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
data = np.random.rand(10, 10) * 100
bounds = [0, 20, 40, 60, 80, 100]
norm = mcolors.BoundaryNorm(bounds, ncolors=256)
fig, ax = plt.subplots(figsize=(8, 6))
im = ax.imshow(data, cmap='RdYlGn', norm=norm)
cbar = fig.colorbar(im, ax=ax, ticks=bounds)
cbar.set_label('Score')
ax.set_title('Discrete Colorbar with BoundaryNorm')
plt.tight_layout()
plt.show()水平方向のカラーバー
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(8, 12)
fig, ax = plt.subplots(figsize=(10, 5))
im = ax.imshow(data, cmap='plasma')
cbar = fig.colorbar(im, ax=ax, orientation='horizontal', fraction=0.046, pad=0.12)
cbar.set_label('Value')
ax.set_title('Horizontal Colorbar')
plt.tight_layout()
plt.show()カスタムカラーマップの作成
組み込みカラーマップが要件に合わない場合(企業ブランドカラー、分野固有の慣習、特定の知覚要件など)、Matplotlibには自作のための2つのクラスが用意されています。
ListedColormap:色のリストから作る
ListedColormap は、明示的な色リストからカラーマップを作成します。各色は[0, 1]範囲の同じ割合を占めます。
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
# Define colors by name, hex, or RGB tuple
colors = ['#2c3e50', '#2980b9', '#27ae60', '#f39c12', '#e74c3c']
cmap_custom = mcolors.ListedColormap(colors)
data = np.random.rand(10, 10)
fig, ax = plt.subplots(figsize=(8, 6))
im = ax.imshow(data, cmap=cmap_custom)
fig.colorbar(im, ax=ax)
ax.set_title('Custom ListedColormap (5 colors)')
plt.tight_layout()
plt.show()LinearSegmentedColormap:滑らかなグラデーション
LinearSegmentedColormap は滑らかな色の遷移を作ります。最も簡単なのは from_list を使う方法で、アンカー色の間を線形補間します。
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
# Smooth gradient from dark blue through white to dark red
colors = ['#1a1a6e', '#4a90d9', '#ffffff', '#d94a4a', '#6e1a1a']
cmap_diverge = mcolors.LinearSegmentedColormap.from_list('custom_diverge', colors)
np.random.seed(42)
data = np.random.randn(12, 12)
fig, ax = plt.subplots(figsize=(8, 6))
im = ax.imshow(data, cmap=cmap_diverge, vmin=-3, vmax=3)
fig.colorbar(im, ax=ax, label='Standard Deviations')
ax.set_title('Custom Diverging Colormap')
plt.tight_layout()
plt.show()上級:セグメント辞書形式
各色チャンネルの遷移を完全に制御したい場合は、セグメント辞書を定義します。各チャンネル(red/green/blue)に対して、アンカー点を指定する (x, y_left, y_right) タプルのリストを与えます。
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
# Custom colormap: black -> blue -> cyan -> yellow -> white
cdict = {
'red': [(0.0, 0.0, 0.0), (0.25, 0.0, 0.0), (0.5, 0.0, 0.0),
(0.75, 1.0, 1.0), (1.0, 1.0, 1.0)],
'green': [(0.0, 0.0, 0.0), (0.25, 0.0, 0.0), (0.5, 1.0, 1.0),
(0.75, 1.0, 1.0), (1.0, 1.0, 1.0)],
'blue': [(0.0, 0.0, 0.0), (0.25, 1.0, 1.0), (0.5, 1.0, 1.0),
(0.75, 0.0, 0.0), (1.0, 1.0, 1.0)]
}
cmap_seg = mcolors.LinearSegmentedColormap('custom_seg', cdict)
data = np.random.rand(10, 10)
fig, ax = plt.subplots(figsize=(8, 6))
im = ax.imshow(data, cmap=cmap_seg)
fig.colorbar(im, ax=ax)
ax.set_title('Segment Dictionary Colormap')
plt.tight_layout()
plt.show()カスタムカラーマップの登録
自作したカラーマップを登録しておくと、組み込みと同様に名前で参照できます。
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
colors = ['#0d0887', '#7e03a8', '#cc4778', '#f89540', '#f0f921']
my_cmap = mcolors.LinearSegmentedColormap.from_list('my_palette', colors)
plt.colormaps.register(cmap=my_cmap)
# Now use it by name anywhere
# plt.imshow(data, cmap='my_palette')カラーマップの反転
カラーマップ名の末尾に _r を付けると反転版を使えます。たとえば、高い値を明るくではなく暗く強調したい場合などに便利です。
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(8, 8)
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
axes[0].imshow(data, cmap='viridis')
axes[0].set_title('viridis (default)')
axes[1].imshow(data, cmap='viridis_r')
axes[1].set_title('viridis_r (reversed)')
plt.tight_layout()
plt.show()すべての組み込みカラーマップには反転版があります(plasma_r, coolwarm_r, RdBu_r, inferno_r など)。
カラーマップの切り詰め(Truncate)と部分抽出
カラーマップの一部だけが必要な場合があります。Colormap.__call__ と np.linspace、ListedColormap を使ってスライスを抽出できます。
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
# Extract the middle 50% of the viridis colormap
full_cmap = plt.colormaps['viridis']
colors = full_cmap(np.linspace(0.25, 0.75, 256))
truncated_cmap = mcolors.ListedColormap(colors)
data = np.random.rand(10, 10)
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
axes[0].imshow(data, cmap='viridis')
axes[0].set_title('Full viridis')
axes[1].imshow(data, cmap=truncated_cmap)
axes[1].set_title('Truncated viridis (25%-75%)')
plt.tight_layout()
plt.show()正規化(Normalization):データを色に割り当てる方法を制御する
正規化は、カラーマップ参照の前に、元のデータ値を[0, 1]に変換する方法を決めます。デフォルトは線形ですが、Matplotlibにはいくつかの代替が用意されています。
| Normalization | Class | When to Use |
|---|---|---|
| Linear | Normalize | デフォルト、均等に分布したデータ |
| Logarithmic | LogNorm | 桁違いのスケールを含むデータ |
| Symmetric log | SymLogNorm | 正負があり、ログ的なスケーリングが欲しい |
| Power | PowerNorm | 任意の非線形圧縮 |
| Two-slope | TwoSlopeNorm | 非対称レンジを持つ発散データ |
| Boundary | BoundaryNorm | 離散的なビン境界 |
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
np.random.seed(42)
data = np.random.lognormal(mean=2, sigma=1.5, size=(20, 20))
fig, axes = plt.subplots(1, 3, figsize=(16, 5))
# Linear (default)
im0 = axes[0].imshow(data, cmap='magma')
fig.colorbar(im0, ax=axes[0])
axes[0].set_title('Linear Normalize')
# LogNorm
im1 = axes[1].imshow(data, cmap='magma', norm=mcolors.LogNorm())
fig.colorbar(im1, ax=axes[1])
axes[1].set_title('LogNorm')
# PowerNorm (gamma=0.5 = square root)
im2 = axes[2].imshow(data, cmap='magma', norm=mcolors.PowerNorm(gamma=0.5))
fig.colorbar(im2, ax=axes[2])
axes[2].set_title('PowerNorm (gamma=0.5)')
plt.tight_layout()
plt.show()データに合ったカラーマップの選び方
適切なカラーマップ選びは、実害のある結果を生む「デザイン判断」です。実用的な判断フレームワークは次の通りです。
-
データは逐次的(低→高)ですか? 逐次カラーマップを使います。まずは
viridis。よりコントラストが必要ならplasmaやinfernoを試します。 -
意味のある中心値からの偏差ですか? 発散カラーマップを使います。穏やかな見た目なら
coolwarm、強いコントラストならRdBu。vminとvmaxは対称に設定します。 -
順序のないカテゴリデータですか? 定性カラーマップを使います。最大10カテゴリなら
tab10、最大20ならtab20。 -
周回(角度・位相など)しますか? 周期カラーマップを使います。現代的な選択としては
twilightが最適です。 -
色覚特性のある閲覧者が含まれますか? 逐次なら
cividisまたはviridis。RdYlGnのような赤緑ペアは避けます。 -
グレースケール印刷されますか?
viridis,plasma,inferno,magmaは明度が単調に増加するため、印刷でも読みやすいです。
アクセシビリティ:色覚特性に配慮したカラーマップ
男性の約8%、女性の約0.5%が何らかの色覚特性を持ち、特に赤と緑の区別が難しいケースが一般的です。知覚的に一様なカラーマップ(viridis, plasma, inferno, magma, cividis)は、代表的な色覚特性の下でも判読できるよう特別に設計されています。
アクセシビリティの観点で避けたいカラーマップ: jet, rainbow, RdYlGn, RdYlBu(赤緑の区別が重要な場合)、hot。
なぜ jet が有害なのか: jet(青→シアン→緑→黄→赤の虹)は知覚的に一様ではなく、データに偽の境界を作ります。実際の値の差が大きい領域が似て見えたり、シアン〜緑付近の小さな差が過剰に強調されたりします。また、デューテラノピア(赤緑色覚)ではほぼ機能しません。
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
data = np.random.rand(15, 15)
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
axes[0].imshow(data, cmap='jet')
axes[0].set_title('jet (avoid for scientific use)')
axes[1].imshow(data, cmap='cividis')
axes[1].set_title('cividis (colorblind-safe)')
plt.tight_layout()
plt.show()利用可能なカラーマップをすべて列挙する
使用中のMatplotlibバージョンで利用できるカラーマップを確認するには以下を使います。
import matplotlib.pyplot as plt
# All colormap names, sorted
all_cmaps = sorted(plt.colormaps())
print(f"Total colormaps: {len(all_cmaps)}")
# Filter out reversed versions
base_cmaps = [c for c in all_cmaps if not c.endswith('_r')]
print(f"Base colormaps (excluding _r): {len(base_cmaps)}")視覚的に表示する例:
import matplotlib.pyplot as plt
import numpy as np
gradient = np.linspace(0, 1, 256).reshape(1, -1)
cmaps_to_show = ['viridis', 'plasma', 'inferno', 'magma', 'cividis',
'coolwarm', 'RdBu', 'seismic',
'tab10', 'Set1',
'twilight']
fig, axes = plt.subplots(len(cmaps_to_show), 1, figsize=(10, len(cmaps_to_show) * 0.5))
fig.subplots_adjust(hspace=0.4)
for ax, name in zip(axes, cmaps_to_show):
ax.imshow(gradient, aspect='auto', cmap=name)
ax.set_ylabel(name, rotation=0, labelpad=80, fontsize=10, va='center')
ax.set_xticks([])
ax.set_yticks([])
fig.suptitle('Matplotlib Colormap Samples', fontsize=14, y=1.01)
plt.tight_layout()
plt.show()PyGWalkerによるインタラクティブ可視化
データセットを対話的に探索していると、各プロットごとにカラーマップを手で設定するのは時間がかかります。PyGWalker (opens in a new tab) は、pandasまたはpolarsのDataFrameをJupyter内でTableau風のインタラクティブUIに変換するオープンソースPythonライブラリです。変数を軸へドラッグし、色エンコーディングを割り当て、可視化タイプを切り替える――といった操作を、カラーマップや描画コードを書かずに行えます。
import pandas as pd
import pygwalker as pyg
# Load your data
df = pd.read_csv('your_data.csv')
# Launch the interactive UI -- color encoding, binning, and filtering are all point-and-click
walker = pyg.walk(df)これは、どの変数を可視化し、どの色エンコーディングが最もパターンを明確にするかを決めている探索的分析の段階で特に有用です。適切な可視化が見つかったら、Matplotlibで厳密なカラーマップ設定として再現することもできます。
よくある落とし穴と回避方法
| Pitfall | Problem | Solution |
|---|---|---|
jet をデフォルトで使う | 知覚的に不均一、アクセシブルでない | viridis など知覚的に一様なマップへ切り替える |
| 逐次データに発散マップを使う | 偽の中点を示唆してしまう | 逐次マップを使う |
| 発散データに逐次マップを使う | 中心より上/下の違いが隠れる | 対称な vmin/vmax を持つ発散マップを使う |
発散マップで vmin/vmax を設定しない | 中立色が0に一致しないことがある | 対称な範囲を明示的に設定する |
| カテゴリが多いのに逐次マップを使う | 色が似て区別しづらい | 定性マップ(tab10, Set1)を使う |
| 色覚特性への配慮がない | 男性の約8%は読めない可能性がある | viridis, cividis を使う、または色覚シミュレーションで検証する |
FAQ
Matplotlibのカラーマップとは何ですか?
Matplotlibのカラーマップは、スカラーの数値を色へ対応付ける関数です。0〜1の値を受け取り、RGBAの色タプルを返します。imshow、scatter、contourf、pcolormesh などで、色のグラデーションとしてデータを可視化するために使われます。plt.colormaps['name'] で取得するか、cmap パラメータに名前の文字列を渡して使用します。
データに対して適切なカラーマップはどう選べばよいですか?
逐次データ(低→高)なら viridis、plasma、inferno。発散データ(中心からの偏差)なら coolwarm や RdBu。カテゴリデータなら tab10 や Set1。角度のような周期データなら twilight。常にアクセシビリティも考慮し、viridis と cividis は色覚特性のある閲覧者にも安全です。
Matplotlibでカスタムカラーマップを作るには?
特定の色のリストから作るなら matplotlib.colors.ListedColormap、アンカー色の間を滑らかに補間するなら matplotlib.colors.LinearSegmentedColormap.from_list('name', colors) を使います。plt.colormaps.register() で登録すれば、名前で利用できます。
Matplotlibでカラーマップを反転するには?
カラーマップ名に _r を付けます。例えば cmap='viridis_r' でviridisの反転版になります。これはすべての組み込みカラーマップで使えます。カスタムカラーマップでは、カラーマップオブジェクトに対して .reversed() を呼び出します。
なぜjetカラーマップは避けるべきですか?
jet は知覚的に一様ではないため、偽の境界を作ってしまい、実際のパターンを隠します。また赤緑色覚では判読できません。Matplotlibがバージョン2.0でデフォルトを jet から viridis に変更したのは、まさにこの問題が理由です。代わりに viridis、plasma、cividis を使いましょう。
Matplotlibプロットにカラーバーを追加するには?
imshow、scatter、contourf などが返すオブジェクトを mappable として plt.colorbar(mappable) を呼び出します。label、orientation('horizontal'/'vertical')、shrink、pad などでカスタマイズできます。さらに細かい制御には cbar.ax からカラーバーのAxesへアクセスします。
まとめ
カラーマップは装飾ではありません。可視化が真実を正確に伝えるのか、それとも誤解を生むのかを左右する機能要素です。Matplotlibは、4つの明確なカテゴリ(逐次・発散・定性・周期)に整理された豊富な組み込みカラーマップに加え、必要なら完全にカスタムのものを作るための道具も提供します。逐次データでは、知覚的に一様なファミリ(viridis, plasma, inferno, magma, cividis)をまず第一候補にするのが基本です。発散データでは coolwarm や RdBu のようなマップを選び、中立色がデータの意味のある中点に必ず一致するよう設定してください。カテゴリには tab10 や Set1。そして常に閲覧者を想定しましょう――色覚特性に配慮したカラーマップの利用は「任意」ではなく、プロとしての実務です。