からっぽのしょこ

読んだら書く!書いたら読む!同じ事は二度調べ(たく)ない

pcolorによるヒートマップの作成

はじめに

 Matplotlibライブラリを利用してヒートマップを作図します。

pcolorによるヒートマップの作成

 matplotlibライブラリのAxes.pcolor()を用いて、ヒートマップを作図します。

 利用するライブラリを読み込みます。

# 利用するモジュール
import matplotlib.pyplot as plt
import numpy as np


 まずは、行数Rと列数Cを指定して、作図に利用する配列xを作成します。

# 行数と列数を指定
R = 5
C = 7

# 配列を作成
x = np.arange(R * C).reshape([R, C])
print(x)
print(x.shape)
[[ 0  1  2  3  4  5  6]
 [ 7  8  9 10 11 12 13]
 [14 15 16 17 18 19 20]
 [21 22 23 24 25 26 27]
 [28 29 30 31 32 33 34]]
(5, 7)

 この例では、グラデーションが分かりやすいように、値が1ずつ大きくなる2次元配列を作成します。
 RCも作図に使います。

 ヒートマップは、pyplot.imshow()またはAxes.imshow()で作成できます。

# ヒートマップを作成
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(9, 6)) # 図の設定
ax.imshow(x) # ヒートマップ
plt.show() # 図を表示

f:id:anemptyarchive:20211001072828p:plain
ヒートマップ

 ただこの方法ではやりたいことができなかったので、別の方法で作成します。

・Axes記法の場合

 オブジェクト指向的に書くやつ。

・基本形の作図

 目的の図となるように少しずつ加工していくので、ここの最後を見れば事足ります。

 Axes.pcolor()で、ヒートマップを作成します。

# ヒートマップを作成
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(9, 6)) # 図の設定
ax.pcolor(x) # ヒートマップ
plt.show() # 図を表示

f:id:anemptyarchive:20211001072848p:plain
ヒートマップ:そのまま

 ここから整形していきます。

 目盛がタイルの境界線に付いているので、タイルごとに付くように位置を調整します。

# ヒートマップを作成
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(9, 6)) # 図の設定
ax.pcolor(x) # ヒートマップ
ax.set_xticks(np.arange(C) + 0.5) # x軸目盛の位置
ax.set_xticklabels(np.arange(C))  # x軸目盛のラベル
ax.set_yticks(np.arange(R) + 0.5) # y軸目盛の位置
ax.set_yticklabels(np.arange(R))  # y軸目盛のラベル
plt.show() # 図を表示

f:id:anemptyarchive:20211001072911p:plain
ヒートマップ:目盛位置の調整

 Axes.xticks()でx軸目盛の位置を指定し、Axes.set_xticklabels()で目盛として表示する文字列を指定します。
 y軸も同様に、Axes.yticks()で目盛の位置を、Axes.set_yticklabels()で目盛のラベルを指定します。

 x軸(y軸)の目盛ラベルに0からC-1(R-1)までの整数を指定しつつ、目盛位置をそれぞれ0.5ズラすことでタイルの真ん中に表示できます。

 np.arange()の第1引数と第2引数を指定することで、表示する値の範囲を変更できます。

# ヒートマップを作成
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(9, 6)) # 図の設定
ax.pcolor(x) # ヒートマップ
ax.set_xticks(np.arange(C) + 0.5) # x軸目盛の位置
ax.set_xticklabels(np.arange(1, C + 1)) # x軸目盛のラベル
ax.set_yticks(np.arange(R) + 0.5) # y軸目盛の位置
ax.set_yticklabels(np.arange(1, R + 1)) # y軸目盛のラベル
plt.show() # 図を表示

f:id:anemptyarchive:20211001073006p:plain
ヒートマップ:目盛位置の調整

 表示する位置についてはそのままです。

 step引数(第3引数)を指定することで、作成する数列の間隔を調整できます。

# 配列を作成
R, C = 10, 100
x = np.arange(R * C).reshape([R, C])

# ヒートマップを作成
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(9, 6)) # 図の設定
ax.pcolor(x) # ヒートマップ
ax.set_xticks(np.arange(C, step=10) + 0.5) # x軸目盛の位置
ax.set_xticklabels(np.arange(C, step=10))  # x軸目盛のラベル
ax.set_yticks(np.arange(R) + 0.5) # y軸目盛の位置
ax.set_yticklabels(np.arange(R))  # y軸目盛のラベル
plt.show() # 図を表示

f:id:anemptyarchive:20211001073021p:plain
ヒートマップ:目盛位置の調整


 配列は0行目が一番上でR-1行目が一番下に表示されますが、この図は逆向きになっています。
 Axes.invert_yaxis()で、y軸を反転させて対応させます。

# ヒートマップを作成
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(9, 6)) # 図の設定
c = ax.pcolor(x) # ヒートマップ
ax.set_xticks(np.arange(C) + 0.5) # x軸目盛の位置
ax.set_xticklabels(np.arange(C))  # x軸目盛のラベル
ax.set_yticks(np.arange(R) + 0.5) # y軸目盛の位置
ax.set_yticklabels(np.arange(R))  # y軸目盛のラベル
ax.invert_yaxis() # y軸を反転
plt.show() # 図を表示

f:id:anemptyarchive:20211001073035p:plain
ヒートマップ:y軸の反転


 figsize引数に指定するサイズによって、タイルが間延びした形になることがあります。
 Axes.set_aspect('equal')で、アスペクト比を等倍に設定します。

# ヒートマップを作成
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(9, 6)) # 図の設定
ax.pcolor(x) # ヒートマップ
ax.set_xticks(np.arange(C) + 0.5) # x軸目盛の位置
ax.set_xticklabels(np.arange(C))  # x軸目盛のラベル
ax.set_yticks(np.arange(R) + 0.5) # y軸目盛の位置
ax.set_yticklabels(np.arange(R))  # y軸目盛のラベル
ax.invert_yaxis() # y軸を反転
ax.set_aspect('equal', adjustable='box') # アスペクト比
plt.show() # 図を表示

f:id:anemptyarchive:20211001073112p:plain
ヒートマップ:アスペクト比の調整


 ラベル類を設定します。

# ヒートマップを作成
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(9, 6)) # 図の設定
ax.pcolor(x) # ヒートマップ
ax.set_xticks(np.arange(C) + 0.5) # x軸目盛の位置
ax.set_xticklabels(np.arange(C))  # x軸目盛のラベル
ax.set_yticks(np.arange(R) + 0.5) # y軸目盛の位置
ax.set_yticklabels(np.arange(R))  # y軸目盛のラベル
ax.set_xlabel('x label') # x軸ラベル
ax.set_ylabel('y label') # y軸ラベル
ax.set_title('title') # タイトル
fig.suptitle('suptitle') # 全体のタイトル
ax.invert_yaxis() # y軸を反転
ax.set_aspect('equal', adjustable='box') # アスペクト比
plt.show() # 図を表示

f:id:anemptyarchive:20211001073132p:plain
ヒートマップ:ラベル付け

 Axes.set_xlabel()でx軸ラベル、Axes.set_ylabel()でy軸ラベルを指定します。
 Axes.set_title()でタイトル、Figure.suptitle()またはpyplot.suptitle()で図全体のタイトルを指定します。

 タイルの色と値の関係が分かるように、カラーバーを表示します。

# ヒートマップを作成
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(9, 6)) # 図の設定
c = ax.pcolor(x) # ヒートマップ
ax.set_xticks(np.arange(C) + 0.5) # x軸目盛の位置
ax.set_xticklabels(np.arange(C))  # x軸目盛のラベル
ax.set_yticks(np.arange(R) + 0.5) # y軸目盛の位置
ax.set_yticklabels(np.arange(R))  # y軸目盛のラベル
ax.set_xlabel('x label') # x軸ラベル
ax.set_ylabel('y label') # y軸ラベル
ax.set_title('title') # タイトル
fig.suptitle('suptitle') # 全体のタイトル
ax.invert_yaxis() # y軸を反転
ax.set_aspect('equal', adjustable='box') # アスペクト比
fig.colorbar(c, ax=ax, label='colorbar label') # カラーバー
plt.show() # 図を表示

f:id:anemptyarchive:20211001073205p:plain
ヒートマップ:カラーバー

 Figure.colorbar()で、カラーバーを表示します。このcって何?なんて呼べばいいの?mappableって?

 以上で(私の)目的の図が完成しました。

・色の設定

 色の設定について少しだけ確認しておきます。

 グラデーションの割り当てに関して、最小値と最大値を変更します。

# ヒートマップを作成
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(9, 6)) # 図の設定
c = ax.pcolor(x, vmin=10, vmax=20) # ヒートマップ
#ax.pcolor(x).set_clim(vmin=10, vmax=20) # グラデーション調整ヒートマップ
ax.set_xticks(np.arange(C) + 0.5) # x軸目盛の位置
ax.set_xticklabels(np.arange(C))  # x軸目盛のラベル
ax.set_yticks(np.arange(R) + 0.5) # y軸目盛の位置
ax.set_yticklabels(np.arange(R))  # y軸目盛のラベル
ax.invert_yaxis() # y軸を反転
ax.set_aspect('equal', adjustable='box') # アスペクト比
fig.colorbar(c, ax=ax) # カラーバー
plt.show() # 図を表示

f:id:anemptyarchive:20211001073225p:plain
ヒートマップ:グラデーションの調整

 最小値の引数vminと最大値の引数vmaxで、グラデーションの範囲を設定します。Mappable.set_clim()でも設定できます。

 グラデーションの色を指定します。

# ヒートマップを作成
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(9, 6)) # 図の設定
c = ax.pcolor(x, cmap='winter') # ヒートマップ
ax.set_xticks(np.arange(C) + 0.5) # x軸目盛の位置
ax.set_xticklabels(np.arange(C))  # x軸目盛のラベル
ax.set_yticks(np.arange(R) + 0.5) # y軸目盛の位置
ax.set_yticklabels(np.arange(R))  # y軸目盛のラベル
ax.set_title('cmap=winter') # タイトル
ax.invert_yaxis() # y軸を反転
ax.set_aspect('equal', adjustable='box') # アスペクト比
fig.colorbar(c, ax=ax) # カラーバー
plt.show() # 図を表示

f:id:anemptyarchive:20211001073256p:plain
ヒートマップ:カラーマップの変更

 Axes.pcolor()のカラーマップ引数cmapにカラーマップ(色名)を指定します。この例は、winterを指定しています。
 cmapに指定できる色については、Matplotlibの公式ドキュメント「Choosing Colormaps in Matplotlib — Matplotlib 3.4.3 documentation」を参照してください。

・pyplot記法の場合

 関数を重ねて書くやつ。

 plt.function()の形式で同じ図を作成します。

# ヒートマップを作成
plt.figure(figsize=(9, 6)) # 図の設定
plt.pcolor(x, cmap='viridis') # ヒートマップ
plt.xticks(ticks=np.arange(C) + 0.5, labels=np.arange(C)) # x軸目盛
plt.yticks(ticks=np.arange(R) + 0.5, labels=np.arange(R)) # y軸目盛
plt.xlabel('x label') # x軸ラベル
plt.ylabel('y label') # y軸ラベル
plt.title('title') # タイトル
plt.suptitle('suptitle') # 全体のタイトル
plt.ylim(ymin=R, ymax=0) # y軸を反転
plt.axes().set_aspect('equal', adjustable='box') # アスペクト比
#plt.clim(-10, 10) # グラデーション
plt.colorbar(label='colorbar label') # カラーバー
plt.show() # 図を表示

f:id:anemptyarchive:20211001073315p:plain
ヒートマップ

 pyplot.xticks()でx軸目盛を設定します。ticksに目盛の位置、labels引数に目盛ラベルを指定します。
 同様に、pyplot.yticks()でy軸目盛を設定します。

 pyplot.ylim()の最小値の引数yminに最大値を、最大値の引数ymaxに最小値を指定するとy軸が反転します(なんで?)。

 plt.axes().set_aspect('equal')でアスペクト比を等倍にできますが、なんかメッセージが出ます(?)。

おわりに

 思いの外調べることが多かったので、メモしておきます。

【関連する記事】

www.anarchive-beta.com