LoginSignup
119
136

More than 5 years have passed since last update.

【Python】matplotlibによるグラフ描画時のColormapのカスタマイズ

Posted at

AdventarPython Advent Calendar 2015 21日目の記事です。

Pythonでグラフを描く時、Matplotlibを使うと思います。また最近はSeabornというグラフを綺麗にしてくれるライブラリがあり、自分はそれを愛用しています。ただ、色をもっと自由に選びたい、設定したいという時に+αでColormapのカスタマイズをすると便利です。今回はこれを紹介します。

準備

まずはいつもの一式インポートです。大体Anacondaにあるものですが、足りないものは pip install <入れたいライブラリ名>で入れることができます。

import numpy as np
import pandas as pd
from sklearn import datasets

import matplotlib.pyplot as plt
import matplotlib.cm as cm
%matplotlib inline
import seaborn as sns

sns.set(style="darkgrid", palette="muted", color_codes=True) 

お試しに使うのは、いつものirisデータセットです。

# irisデータのロード
iris = datasets.load_iris()

そのまま素直に、irisの種別ごとに色分けして散布図を描くとこんな感じで、白黒になってしまいます・・・。

# 散布図の表示(色が白黒になってしまう・・・)
plt.figure(figsize=(10,7))
plt.scatter(iris.data[:,0], iris.data[:,1], linewidths=0, alpha=1,
            c=iris.target   # iris.targetには種別を表す[0, 1, 2]が入っているのでそれで色分け
           )
plt.show()

plot_01.png

引数cに個別に色の名前を指定すると色を指定することが出来ます。でもあんまりスマートじゃない感じがします。

# 散布図の表示(ひとつずつ色を指定する)
def set_color(l):
    if l == 0:
        return "b"  # blue
    elif l == 1:
        return "g"  # green
    else:
        return "r"  # red

color_list = map(set_color, iris.target)

plt.figure(figsize=(10,7))
plt.scatter(iris.data[:,0], iris.data[:,1], linewidths=0, alpha=1,
            c=iris.target   # iris.targetには種別を表す[0, 1, 2]が入っているのでそれで色分け
           )
plt.show()

plot_02.png

種別ひとつずつに色を指定するのも大変なので、元々Matplotlibで定義されているカラーマップを使うこともできます。カラーマップについてはここを参考にすると様々なカラーマップの定義を見ることができます。

# 定義されているカラーマップを適用する
# 参考: http://matplotlib.org/examples/color/colormaps_reference.html

fig = plt.figure(figsize=(13,7))
im = plt.scatter(iris.data[:,0], iris.data[:,1], c=iris.target, linewidths=0, alpha=1, 
                 cmap=cm.Accent # ここでカラーマップを指定
                )
fig.colorbar(im)
plt.show()

でもちょっと欲しい色にバッチリ合わせるのが難しいですね・・・。
plot_03.png

Colormapのカスタマイズ

そこで、自分でこのカラーマップをカスタマイズして定義してみます。
色名もしくは16進のカラーコードをリストで指定すると、間を滑らかに線形補完しながらカラーマップを作ってくれます。日本語でうまく説明できないので、使用例を見てみましょう。

# colormapをカスタマイズする
from matplotlib.colors import LinearSegmentedColormap

def generate_cmap(colors):
    """自分で定義したカラーマップを返す"""
    values = range(len(colors))

    vmax = np.ceil(np.max(values))
    color_list = []
    for v, c in zip(values, colors):
        color_list.append( ( v/ vmax, c) )
    return LinearSegmentedColormap.from_list('custom_cmap', color_list)

irisデータは3種類なので、3つの色を指定します。使える色名称については、ここを参考にすると一覧で見ることができます。

# 色をカスタマイズ, その1:色名称で指定
# 参考: http://matplotlib.org/examples/color/named_colors.html
unique_value = set(iris.target)
print unique_value
# --> [0, 1, 2]

cm = generate_cmap(['mediumblue', 'limegreen', 'orangered'])

fig = plt.figure(figsize=(13,7))
im = plt.scatter(iris.data[:,0], iris.data[:,1], c=iris.target, linewidths=0, alpha=.8, cmap=cm)
fig.colorbar(im)
plt.show()

plot_04.png

色の名称ではなく、16進表現で指定することもできます。16進表現のカラーコードはこちらが参考になりました

# 色をカスタマイズ, その2:16進で指定
# http://www5.plala.or.jp/vaio0630/hp/c_code.htm

cm = generate_cmap(['#87CEEB', '#2E8B57', '#F4A460'])

fig = plt.figure(figsize=(13,7))
im = plt.scatter(iris.data[:,0], iris.data[:,1], c=iris.target, linewidths=0, alpha=.8, cmap=cm)
fig.colorbar(im)
plt.show()

plot_04-2.png

淡い色を指定した時は、背景がグレーよりも白の方が見やすいです。seabornで変更できるので背景を白にしてみます。

# 色をカスタマイズ, その3:背景を白くする
sns.set(style="whitegrid", palette="muted", color_codes=True)

cm = generate_cmap(['#87CEEB', '#2E8B57', '#F4A460'])

fig = plt.figure(figsize=(13,7))
im = plt.scatter(iris.data[:,0], iris.data[:,1], c=iris.target, linewidths=0, alpha=.8, cmap=cm)
fig.colorbar(im)
plt.show()

plot_05.png

次に、平面座標(2つの変数)を引数に取る関数の値を色で表現してみます。カラーマップのカスタマイズはこういったケースでとても有効ですね。

# 滑らかな塗りつぶし
n = 501
X, Y = np.meshgrid(np.linspace(0, 1, n), np.linspace(0, 1, n))
Z = np.sin(X*30) + np.cos(Y*30)
print np.min(Z), np.max(Z)

cm = generate_cmap(['#00008B', '#aaaaab', '#FFFFFF', '#F4D793', '#F4A460'])

fig =plt.figure(figsize=(10,8))
im = plt.pcolor(X, Y, Z, cmap=cm)

fig.colorbar(im)
plt.xlim(0, 1)
plt.ylim(0, 1)
plt.show()

plot_06.png

最後に、等高線の高さを色で表現してみる例です。こちらもカラーマップでグラデーション含め指定できることがとても有効です。

# 等高線
n = 201
X, Y = np.meshgrid(np.linspace(0, 1, n), np.linspace(0, 1, n))
Z = np.sin(X*20) * np.cos(Y*20)

cm = generate_cmap(['indigo', 'white', 'salmon'])

fig =plt.figure(figsize=(10,8))
interval = [i/10. -1 for i in range(20)]
im = plt.contour(X, Y, Z, interval, alpha=0.5, cmap=cm)

fig.colorbar(im)
plt.xlim(0, 1)
plt.ylim(0, 1)
plt.show()

plot_07.png

本記事のコード

GitHubにコードを掲載しています。
https://github.com/matsuken92/Qiita_Contents/blob/master/General/Matplotlib_color_settings.ipynb

参考

Matplotlib colormaps reference
 http://matplotlib.org/examples/color/colormaps_reference.html
Making a custom colormap using matplotlib in python (stackoverflow)
 http://stackoverflow.com/questions/24997926/making-a-custom-colormap-using-matplotlib-in-python
名前が定義されている色一覧
 http://matplotlib.org/examples/color/named_colors.html
16進カラーコード
 http://www5.plala.or.jp/vaio0630/hp/c_code.htm

119
136
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
119
136