こんにちは、でめきんです。
matplotlibを使ってカラー表示をする際、既存のカラーマップでは満足がいかないことがあると思います。
そんな時は自作でカラーマップを作ってしまおうというのが今回の企画です。
準備
カラーマップ表示するには、どの値からどの値までを、どの様な区切りで表示するか考えます。
その後、その区切りをどの色で表示するか決めます。
今回は0~99までの値を10区切りで、色を
[ black , lightgrey , darkorange , gole , chartreuse , palegreen , mediumspringgreen , paleturquoise , steelblue , navy ]
上記10色で表示してみたいと思います。
matplotlibのカラー表示はここで確認できます。
seaborn
今回はseabornのヒートマップを用いて確認をしてみます。
ちなみに、seabornはデータの可視化をmatplotlibよりも強力にサポートしてくれるライブラリーです。
今回提示するヒートマップもseabornならではの機能です。
seabornはmatplotlibと違うライブラリーかと思われるかもしれませんが、実は内部ではmatplotlibが動いているらしいです。
もちろん、カラーマップの設定はmatplotlibでも利用できますのでご安心を。
等間隔で色を付けたい場合
色を指定します。先ほども提示しましたが再度掲示します。
cmap = ListedColormap(
[ 'black' , 'lightgrey' , 'darkorange' , 'gold' , 'chartreuse' ,
'palegreen' , 'mediumspringgreen' , 'paleturquoise' , 'steelblue' , 'navy' ])
ここで注意していただきたいので色の名前はシングルコーテーション「 ‘ 」で囲う必要があります。
それでは、コードを提示します。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap, BoundaryNorm
import seaborn as sns
arr = np.arange(100)
arr = arr.reshape([10,10])
print(arr)
fig=plt.figure(figsize=(5, 5))
ax1 = fig.add_subplot(1,1,1)
ax1.axes.xaxis.set_visible(False), ax1.axes.yaxis.set_visible(False)
ax1.spines['bottom'].set_visible(False), ax1.spines['top'].set_visible(False)
ax1.spines['right'].set_visible(False), ax1.spines['left'].set_visible(False)
cmap = ListedColormap(
[ 'black' , 'lightgrey' , 'darkorange' , 'gold' , 'chartreuse' ,
'palegreen' , 'mediumspringgreen' , 'paleturquoise' , 'steelblue' , 'navy' ])
norm = BoundaryNorm(bounds, cmap.N)
ax1 = sns.heatmap(arr, annot=True, cbar=True, cmap=cmap)
plt.show()
きちんと10間隔で設定した色通りに表示されています。
等間隔で色を変えたい場合はこれでいいのですが、例えば40~60の間だけ色を変えたい場合はこれではうまくいきません。
等間隔ではなく、特定の区間だけ色を変えたい場合
ある領域だけ色を変えたい場合はまず色分けする領域を指定する必要があります。
30~70の間だけを5づつ色を付けたい場合、まず色の指定範囲を以下のように設定します。
bounds = [0, 30, 35, 40, 45, 50, 55, 60, 65, 70, 100]
ただ、これだけだと範囲と色の組み合わせができていません。
なので「BoundaryNorm」という関数を使って紐づけしてあげます。
norm = BoundaryNorm(bounds, cmap.N)
ちなみに、cmapの後の「 .N 」とはboundsとcmapに対応させる意味があるらしいです。これが無いとエラーになります。
そして、これを画像設定axの中に組み込んでいきます。
ax1 = sns.heatmap(arr, annot=True, cbar=True, cmap=cmap, norm=norm)
コード全体としては
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap, BoundaryNorm
import seaborn as sns
arr = np.arange(100)
arr = arr.reshape([10,10])
print(arr)
fig=plt.figure(figsize=(5, 5))
ax1 = fig.add_subplot(1,1,1)
ax1.axes.xaxis.set_visible(False), ax1.axes.yaxis.set_visible(False)
ax1.spines['bottom'].set_visible(False), ax1.spines['top'].set_visible(False)
ax1.spines['right'].set_visible(False), ax1.spines['left'].set_visible(False)
cmap = ListedColormap(
[ 'black' , 'lightgrey' , 'darkorange' , 'gold' , 'chartreuse' ,
'palegreen' , 'mediumspringgreen' , 'paleturquoise' , 'steelblue' , 'navy' ])
bounds = [0, 30, 35, 40, 45, 50, 55, 60, 65, 70, 100]
norm = BoundaryNorm(bounds, cmap.N)
ax1 = sns.heatmap(arr, annot=True, cbar=True, cmap=cmap, norm=norm)
plt.show()
matplotlibではどうする?
ax1 = sns.heatmap(arr, annot=True, cbar=True, cmap=cmap, norm=norm)
の部分を以下に変更すれば完了です。
ax1.imshow(arr, cmap=cmap, norm=norm)
なお、matplotlibで値を表示する機能は標準ではないと思われますので、もし値を表示したい方はseabornを用いた方が簡便でいいかと思われます。
お疲れ様でした。