Help us understand the problem. What is going on with this article?

heatmapに斜線 (hatch) を加える (python, matplotlib)

はじめに

ヒートマップ上で特定の値を示す部分に斜線('/')を描きたかったので,メモ.

やりたいこと

以下のようなヒートマップで,特定の値の部分を斜線でいい感じにしたい.

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

np.random.seed(0)
Z =np.random.rand(10, 10)
Zm = Z * 0
Z[3:5, 5:8] = 1
fig, ax = plt.subplots(figsize=(9, 7))
ax1 = ax.pcolormesh(Z)
fig.colorbar(ax1)

image.png

上の図では,Z[3:5, 5:8] = 1として図の一部の値を1に設定しています.
このZ[3:5, 5:8]の部分に斜線を引きます.

解決方法

最終的なコードは以下.

np.random.seed(0)
Z =np.random.rand(10, 10)
Zm = Z * 0
Z[3:5, 5:8] = 1
fig, ax = plt.subplots(figsize=(9, 7))
ax1 = ax.pcolormesh(Z)

Zm = np.ma.masked_where(Z!=1, Z)
ax2 = ax.pcolor(Zm, hatch='/', edgecolor='grey',facecolor='none', linewidth=0.0)

fig.colorbar(ax1)

image.png

何をしているか

上記のコードで,最初と異なるのは以下の2行です.

Zm = np.ma.masked_where(Z!=1, Z)
ax2 = ax.pcolor(Zm, hatch='/', edgecolor='grey',facecolor='none', linewidth=0.0)

1行目:行列のマスク

一部のみ斜線で示すために,コードの1行目でその部分を表す行列(Zm)を作成しています.

numpy.ma.masked_where を用いることで,条件に該当する部分が無効にされた(マスクされた)行列を作成することができます.
参考:numpy.ma.masked_where 公式ドキュメント

もともとの行列(Z)とマスクされた行列(Zm)は以下のようになっています.
スクリーンショット 2019-12-03 13.53.23.png

スクリーンショット 2019-12-03 13.53.33.png

行列の中身を見ると,Zmでは,条件式(Z!=1)に該当する要素以外は--で表されています.
プロット時にこの行列Zmを用いることで,条件式に該当する部分は無視してプロットを行うことができます.

2行目:hatchで斜線を描画

参考:python – matplotlib 2.0で領域をハッチのみ(背景色なし)で埋めるにはどうすればいいですか?

コードの2行目では,行列Zmを用いて斜線を描画しています.
matplotlib.pyplot.pcolorでは,以下のパターンのhatchを用いることができます.

/ - diagonal hatching
\ - back diagonal
| - vertical
- - horizontal
+ - crossed
x - crossed diagonal
o - small circle
O - large circle
. - dots
* - stars

参考:matplotlib.collections.Collection.set_hatch

ここで使用したオプションは以下の通りです.

  • edgecolor:hatch の色
  • facecolor:hatchの背景色.'none'に設定することでヒートマップの色を残してhatchのみを表示させることができる.
  • linewidth:グリッドの太さ.0より大きい値を指定するとグリッドが表示される.

オプションを変更したときの図の外観は以下のようになります.
ax.pcolorの行以外は最終的なコードと同じです)

ax2 = ax.pcolor(Zm, hatch='/', edgecolor='grey',facecolor='none', linewidth=1.0)

image.png

ax2 = ax.pcolor(Zm, hatch='/', edgecolor='grey',linewidth=0.0)

image.png

ax2 = ax.pcolor(Zm, hatch='/', edgecolor='red',facecolor='none', linewidth=0.0)

image.png

参考サイト一覧

numpy.ma.masked_where 公式ドキュメント
python – matplotlib 2.0で領域をハッチのみ(背景色なし)で埋めるにはどうすればいいですか?
matplotlib.collections.Collection.set_hatch

stktu_KU
Doctor course student @ Kyoto University 化学プロセスのモデリングに取り組み中・・・ データ解析・自然言語処理も使います. 主な使用言語はMATLAB,Python.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away