本記事では、カラーマップの範囲をどのように指定・調整するかについて詳しく解説します。
カラーマップの範囲とは
colormap の「範囲」とは、データの最小値から最大値までの数値が、colormap のどの部分に対応するかを決定する設定のことです。具体的には、以下の要素が関係します。
- vmin と vmax: imshow や scatter などの関数で、描画対象のデータの最小値 (
vmin
) と最大値 (vmax
) を設定することができます。これにより、データ値が colormap のどの部分にマッピングされるかが決まります。 - Normalization(正規化): デフォルトでは線形正規化が適用されますが、
matplotlib.colors.Normalize
やLogNorm
を使用することで、非線形なマッピングも可能です。
これらの設定は、データのダイナミックレンジが広い場合や、極端な外れ値が存在する場合に特に有用です。適切な範囲設定を行うことで、データの特徴が強調されます。
範囲設定の方法
vmin と vmax の指定
最もシンプルな方法は、描画関数に vmin
と vmax
の引数を渡す方法です。以下は imshow
を用いた例です。
import matplotlib.pyplot as plt
import numpy as np
# 例としてランダムなデータを生成(0~100の範囲)
data = np.random.rand(10, 10) * 100
fig, ax = plt.subplots()
# vmin=20, vmax=80 として、20以下および80以上の値は同じ色で表現される
cax = ax.imshow(data, cmap='viridis', vmin=20, vmax=80)
cbar = fig.colorbar(cax)
plt.title("vmin と vmax を用いた colormap の範囲設定")
plt.show()


この例では、データのうち 20 未満と 80 超の値は、colormap の端の色にマッピングされます。これにより、データの主要な部分に焦点を当てることができます。
後から範囲指定を変更する方法
すでに作成した画像オブジェクトに対して、後から colormap の範囲を変更することも可能です。これは、インタラクティブなプロット作成時に便利です。
import matplotlib.pyplot as plt
import numpy as np
data = np.random.rand(10, 10) * 100
fig, ax = plt.subplots()
cax = ax.imshow(data, cmap='plasma')
cbar = fig.colorbar(cax)
# 後から範囲を変更
cax.set_clim(30, 70)
plt.title("set_clim を用いた colormap の範囲変更")
plt.show()

高度な範囲指定方法
正規化オブジェクトを用いるとより柔軟な範囲指定ができます。
線形正規化(Linear Normalization)
最も基本的な方法です。matplotlib.colors.Normalize
クラスがこれに該当し、指定した vmin
と vmax
の間でデータを線形に [0, 1] にマッピングします。結果は上で見た方法と同等になります。
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import Normalize
data = np.random.rand(10, 10) * 100
fig, ax = plt.subplots()
# デフォルトの線形正規化の代わりに、正規化オブジェクトを明示的に指定
norm = Normalize(vmin=25, vmax=75)
cax = ax.imshow(data, cmap='viridis', norm=norm)
cbar = fig.colorbar(cax)
plt.title("Normalize を用いた正規化による範囲設定")
plt.show()

この方法では、vmin
(この例では 20 )以下の値は 0 に、vmax
(80)以上の値は 1 にマッピングされ、中間の値は線形に補間されます。
対数正規化(Logarithmic Normalization)
データが対数的なスケールに分布している場合、matplotlib.colors.LogNorm
を用いることで、対数スケールに沿った正規化が可能です。これにより、非常に大きな値と小さな値の両方を効果的に可視化できます。

べき乗正規化(PowerNorm)
PowerNorm は、べき乗(パワー)を用いてデータを非線形に [0, 1] の範囲にスケーリングします。
- gamma パラメータ:
gamma < 1
の場合、低い値がより強調されるgamma > 1
の場合、高い値がより強調される
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import PowerNorm
# 0~100 の範囲のランダムデータを生成
data = np.random.rand(10, 10) * 100
fig, ax = plt.subplots()
# gamma=0.5 により、低い値を強調する
norm = PowerNorm(gamma=0.5, vmin=0, vmax=100)
cax = ax.imshow(data, cmap='viridis', norm=norm)
fig.colorbar(cax)
plt.title("PowerNorm (gamma=0.5) を用いた正規化")
plt.show()

この例では、gamma=0.5
を設定することで、低い値の違いが視覚的に際立つようになり、データの分布の特徴を強調することができます。
対称な対数スケール(SymLogNorm)
SymLogNorm は、対称な対数スケールによる正規化を行います。
- linthresh: 中心付近(通常 0 を含む)で線形スケールを適用する範囲を指定
- vmin, vmax: データの最小値と最大値を設定
- base: 対数の底を指定(デフォルトは 10)
特に、正負の値が混在するデータの場合に有用で、0 に近い領域は線形、極端な値は対数的に変換されます。
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import SymLogNorm
# -10~10 の範囲の x, y 座標を生成し、X*Y の形でデータ作成(正負両方の値を含む)
x = np.linspace(-10, 10, 100)
y = np.linspace(-10, 10, 100)
X, Y = np.meshgrid(x, y)
data = X * Y
fig, ax = plt.subplots()
# linthresh=1 で、[-1, 1] の範囲は線形に変換される
norm = SymLogNorm(linthresh=1, vmin=-100, vmax=100, base=10)
cax = ax.imshow(data, cmap='coolwarm', norm=norm)
fig.colorbar(cax)
plt.title("SymLogNorm を用いた正規化 (linthresh=1)")
plt.show()

この例では、linthresh=1
を指定することで、値が -1~1 の間は線形に変換され、極端な値は対数スケールで補間されます。正負両方向のスケールが対称的に扱われるため、データのゼロ周辺の変化がわかりやすくなります。
両側のスケールを制御(TwoSlopeNorm)
TwoSlopeNorm は、中心値(vcenter)を基準に、正と負(または中心より大きい値と小さい値)で異なる正規化を行う手法です。
- vmin, vcenter, vmax を指定することで、中心値を境にした両側のスケールを個別に制御します。
- 特に、発散系(ダイバージング)カラーマップと併用する場合に有効です。
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import TwoSlopeNorm
# -10~30 の範囲のランダムデータを生成
data = np.random.rand(10, 10) * 40 - 10 # 値の範囲: -10~30
fig, ax = plt.subplots()
# vcenter=10 を中心値として設定
norm = TwoSlopeNorm(vmin=-10, vcenter=10, vmax=30)
cax = ax.imshow(data, cmap='bwr', norm=norm)
fig.colorbar(cax)
plt.title("TwoSlopeNorm を用いた正規化 (vcenter=10)")
plt.show()

この例では、vcenter=10
を設定することで、値が 10 を境にして正規化が異なるスロープで行われます。これにより、中心付近のデータ変化を強調し、正負の偏りを視覚的に表現することが可能になります。
まとめ
- vmin と vmax を利用することで、シンプルかつ効果的にデータの主要部分に焦点を合わせることができます。
- set_clim を用いた後からの変更は、インタラクティブな調整に便利です。
- Normalize オブジェクト による正規化のカスタマイズは、データの特性に合わせた柔軟な対応を可能にします。
- 線形正規化 ではシンプルな変換が行われ、
vmin
とvmax
に基づいてデータを [0, 1] にマッピングします。 - 対数正規化 や その他の特殊な正規化手法 は、データの分布特性に応じた非線形な変換を実現し、より適切な可視化を可能にします。
- 線形正規化 ではシンプルな変換が行われ、
データの分布や目的に合わせて使い分けることで、より効果的なデータ可視化が実現できます。