Python : seabornのヒートマップを回転させたりマスクさせたり

# 1. はじめに
seabornのヒートマップの調整を図ります。

具体的には、ヒートマップの回転とマスクを行います。



# 2. 準備
## 2.1. 環境
Python 3.7.1を使用しています。
使用環境はJupyter notebookです。

## 2.2. 必要なライブラリ
```python
import numpy as np
import seaborn as sns
```


# 3. ヒートマップの回転
ヒートマップをぐるぐるさせます。

## 3.1. まずは行列を回転

```python
heat = np.array([[0,1],[2,3]])

# 入力
print(
np.rot90(heat, k=0), 
np.rot90(heat, k=1),
np.rot90(heat, k=2),
np.rot90(heat, k=3),
sep='\n\n')

# 出力
[[0 1]
 [2 3]]

[[1 3]
 [0 2]]

[[3 2]
 [1 0]]

[[2 0]
 [3 1]]
```

90°ずつ回転していることが確認できると思います。


## 3.2. ヒートマップで可視化

```python
# DATAを可視化したい行列と書き換える
sns.heatmap(DATA, cmap='Blues',
            square=True, cbar_kws={"shrink": .5},
            xticklabels=0, yticklabels=0)
```

「3.1.まずは行列を回転」の4つの結果を可視化すると、
下記の図のようにぐるぐると回転した結果が得られます。

<img width="640" alt="1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555056/5e558cdb-0938-dfc4-02d8-bc6cf67aefcb.png">


## 3.2. 行列を左右反転

```python
heat = np.array([[0,1],[2,3]])

# 入力
print(
np.rot90(heat, k=1).T,  # == np.rot90(heat, k=2)[::-1],
np.rot90(heat, k=2).T,  # == np.rot90(heat, k=3)[::-1],
np.rot90(heat, k=3).T,  # == np.rot90(heat, k=4)[::-1],
np.rot90(heat, k=4).T,  # == np.rot90(heat, k=5)[::-1],
sep='\n\n')

# 出力
[[1 0]
 [3 2]]

[[3 1]
 [2 0]]

[[2 3]
 [0 1]]

[[0 2]
 [1 3]]
```

*heat* の左右反転した行列が90°ずつ回転していることが確認できると思います。

可視化すると下記の図のようになります。

<img width="640" alt="2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555056/7589ae94-04d7-199c-d27d-868f402d185c.png">




# 4. ヒートマップのマスク
ヒートマップのいらないところをマスクします。


## 4.1. マスクの前処理
目的に合わせて変更してください。

```python
heat = np.ones((3,3))

# 1. 上三角行列をマスクする
mask = np.zeros((len(heat),len(heat)))
mask[np.triu_indices_from(mask, k=0)] = True  # k=1で対角成分を含める

# 2. 下三角行列をマスクする
mask = np.zeros((len(heat),len(heat)))
mask[np.tril_indices_from(mask, k=0)] = True  # k=1で対角成分を含める

# 3. 対角行列をマスクする
mask = np.eye(len(heat))

# 4. 特定の値をマスクする
mask = np.zeros((len(heat),len(heat)))
mask[np.where(heat==1)] = True                # np.where()の中に条件を入れる
```


## 4.2. ヒートマップで可視化

```python
# DATAを可視化したい行列と書き換える
sns.heatmap(DATA, cmap='Blues',
            square=True, cbar_kws={"shrink": .5},
            xticklabels=0, yticklabels=0, mask=mask)
```

マスクをしていないものから順にみてみます。

0. マスクなし
![0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555056/cfcb745f-13ff-e0f7-c150-6acce5e526c2.png)

1. 上三角行列をマスク
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555056/3e7324a6-091f-d9dd-5794-d1afa9e10cb5.png)

2. 下三角行列をマスク
![c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555056/dbd1c4c4-2487-f45f-649c-01732ff15bff.png)

3. 対角行列をマスク
![k.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555056/1ba776f0-92cf-fb26-f680-10a7389cb330.png)

4. 特定の値をマスク
![f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555056/6f64d677-deb9-2d64-0c7a-87af8d23e89b.png)


## 4.3. マスクではなく0に変換
マスクをするのではなく、その成分を「0」に変換したい場合を考えます。
具体的には、maskが1の時の行列を取得して、該当する箇所を0に書き換えます。

```python
for i in range(len(np.where(mask[:]==1)[0])):
    heat[np.vstack(np.where(mask[:]==1)).T[i][0], np.vstack(np.where(mask[:]==1)).T[i][1]]=0
```



# 5. 最後に
seabornのヒートマップの調整をいろいろと書いてみましたが、いかかだったでしょうか。
分かりづらい点や間違っている点があれば、ご指摘いただけると幸いです。



# 参考URL
・NumPy配列ndarrayを回転するnp.rot90
https://note.nkmk.me/python-numpy-rot90/

・numpy.triu_indices
https://docs.scipy.org/doc/numpy/reference/generated/numpy.triu_indices.html