matplotlibのcolormapにブランドイメージカラーを適応してみよう！

## はじめに
matplotlibでグラフを描画する際、皆さんはどんなカラーを利用していますか？
matplotlibにはデフォルトで綺麗な[colormap](https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html)が用意されていますが、
プレゼンのために異なるカラーバリエーションを使いたいとか資料とグラフの
カラーイメージを統一したいとか思ったことはないでしょうか。

本記事では、matplotlibのcolormapへのブランドカラーイメージの
適応にチャレンジしてみます！

## 利用するクラス

matplotlibには独自でcolormapを作成するためのクラスが２種類用意されています。

### 1. [matplotlib.colors.ListedColormap](https://matplotlib.org/3.1.0/api/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib.colors.ListedColormap)

colormapを構成するカラーコードをlistまたはarrayで設定して作成します。
作成されるcolormapの構成色は離散的に変化します。


【利用例】

```{Python}
import matplotlib as mpl
color_list = ['red', 'green', 'blue']
cmap = mpl.colors.ListedColormap(color_list)
```

【作成されるcolormap】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541257/71c3777d-2461-6947-1dd0-706ffa955e48.png)


### 2. [matplotlib.colors.LinearSegmentedColormap](https://matplotlib.org/3.1.0/api/_as_gen/matplotlib.colors.LinearSegmentedColormap.html#matplotlib.colors.LinearSegmentedColormap)

colormapを構成するRGB情報を規定のデータ形式で設定して作成します。
作成されるcolormapの構成色は連続的に変化します。


【利用例】

```{Python}
import matplotlib as mpl

#########################################################################
# 
# 【構成色の設定】
#
# 構成色のデータは,
# [
#  (x_0, y_0, z_0)
#  ...
#  (x_i, y_i, z_i)
# ]
# の構造をとり、RGB値を0～1の値で設定する。
# colormapの構成色は z_0 -> y_1, z_1 -> y_2, ... の順で連続的に変化する。
# 下記の設定だと red -> green, green -> blue　の変化を意味する。
#
#########################################################################

segment_data = {    
    'red':
        [
            (0.0,   0/255, 255/255),
            (0.5,   0/255,   0/255),
            (1.0,   0/255,   0/255),
        ],
    'green':
        [
            (0.0,   0/255,   0/255),
            (0.5, 128/255, 128/255),
            (1.0,   0/255,   0/255),
        ],
    'blue':
        [
            (0.0,   0/255,   0/255),
            (0.5,   0/255,   0/255),
            (1.0, 255/255,   0/255),
        ],
}
cmap = mpl.colors.LinearSegmentedColormap('colormap_name', segment_data)

```

上記の実装だと構成色の設定が直観的でなくちょっと大変ですが、
[matplotlib.colors.LinearSegmentedColormap.from_list](https://matplotlib.org/3.1.0/api/_as_gen/matplotlib.colors.LinearSegmentedColormap.html#matplotlib.colors.LinearSegmentedColormap.from_list)を利用すると
カラーコードのlistで作成できます。

```{Python}
# listで作成する場合
import matplotlib as mpl
color_list = ['red', 'green', 'blue']
cmap = mpl.colors.LinearSegmentedColormap.from_list('colormap_name', color_list)
```

【作成されるcolormap】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541257/41c87e77-fcf8-844a-dd99-fbb9d31fc42f.png)


## 実装

実際に自作colormapを作成する際は、matplotlib.cm.register_cmapで作成したcolormapを
登録しておくと便利です。

```{Python}
import matplotlib.pyplot as plt
import matplotlib as mpl

def set_custom_colormap(name: str, color_list: list):
    
    """
    color_listをcolormap化し、nameでmatplotlibに登録する。
    colormapは離散型と連続型の２パターン及び逆順で４パターン登録される。
    """

    cmap_dis = mpl.colors.ListedColormap(color_list)
    cmap_seq = mpl.colors.LinearSegmentedColormap.from_list(name, color_list)
    
    plt.register_cmap(name + '_dis', cmap_dis)
    plt.register_cmap(name + '_dis_r', cmap_dis.reversed())
    plt.register_cmap(name + '_seq', cmap_seq)
    plt.register_cmap(name + '_seq_r', cmap_seq.reversed())

    return

```

後は自分の設定したい色のカラーコードを調べればOKです。

#### SENSY colormap

```{Python}
COLORMAP_SOURCE_DICT = {
    
    # 単色グラデーション
    'sensy_single_1': ['#FFFFFF', '#F4458C'],
    'sensy_single_2': ['#FFFFFF', '#FF6B9A'],
    'sensy_single_3': ['#FFFFFF', '#FA8EB5'],
    'sensy_single_4': ['#FFFFFF', '#A7C0FD'],
    'sensy_single_5': ['#FFFFFF', '#5073ED'],
    'sensy_single_6': ['#FFFFFF', '#4E6FF0'],
    'sensy_single_7': ['#FFFFFF', '#4B4C80'],
    'sensy_single_8': ['#FFFFFF', '#2B2C4B'],
    
    # 多色グラデーション
    'sensy': ['#FF6B9A', '#4E6FF0'],
    'sensy_diverge': ['#FF6B9A', '#FFFFFF', '#4E6FF0'],
    'sensy_accent': ['#5073ED', '#FA8EB5', '#A7C0FD', '#2B2C4B', '#F4458C', '#4B4C80'],

}

# colormap作成&登録
for name, color_list in COLORMAP_SOURCE_DICT.items():
    set_custom_colormap(name, color_list)


# 初期設定 ###################

# 初期colormap
DEFAULT_COLORMAP = 'sensy_accent_dis'

# matplotlibを利用する場合
mpl.rcParams['image.cmap'] = DEFAULT_COLORMAP

# seabornを利用する場合
import seaborn as sns
sns.set()
sns.set_palette(DEFAULT_COLORMAP)

      
```

【colormapイメージ】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541257/9438f0f4-911b-196f-4126-e9b91345ddf6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541257/1cfd1bd1-6fbe-9b23-f970-0c4df90d5065.png)
　※ colormap名のsuffixが'seq'は連続型、'dis'は離散型になります。
　　また末尾に'_r'をつけると色の順序が逆転します。


【適応イメージ】

|グラフの種類|イメージ|
|:--:|:--:|
|棒グラフ|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541257/56bc1100-5d27-c9ab-11e6-f564a6e97349.png)|
|散布図|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541257/05f526b8-7ee6-6a52-eb63-ba8b57711479.png)|
|等高線|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541257/7bf99d16-e90d-e236-695f-05c76baaa81a.png)|
|ヒートマップ|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541257/67b97462-a838-240f-bdbf-95facc40a237.png)|

※ グラフ描画に利用したデータとコードは [Official seaborn tutorial](https://seaborn.pydata.org/tutorial.html#tutorial) を参考にしています。


## おわりに

利用したいカラーコードが分かるのであれば、簡単に自作のcolormapを作成することができました。
普段利用しているグラフのカラーバリエーションに物足りなさや統一感のなさを感じてきたら、
自分で綺麗なcolormapを作ってみるのも楽しいかもしれませんね。


## 参考

- Matplotlib<br>
  - [Choosing Colormaps in Matplotlib](https://matplotlib.org/3.1.0/index.html)
  - [Creating Colormaps in Matplotlib](https://matplotlib.org/3.1.0/tutorials/colors/colormap-manipulation.html)
  - [Customized Colorbars Tutorial](https://matplotlib.org/3.1.0/tutorials/colors/colorbar_only.html#sphx-glr-tutorials-colors-colorbar-only-py)
  - [Matplotlib API Reference](https://matplotlib.org/3.1.0/api/index.html#)
  <br><br>
- Seaborn
  - [Official Seaborn Tutorial](https://seaborn.pydata.org/tutorial.html)
  <br><br>
- [【Python】matplotlibによるグラフ描画時のColormapのカスタマイズ](https://qiita.com/kenmatsu4/items/fe8a2f1c34c8d5676df8)