AdventarのPython 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()
引数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()
種別ひとつずつに色を指定するのも大変なので、元々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()
でもちょっと欲しい色にバッチリ合わせるのが難しいですね・・・。
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()
色の名称ではなく、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()
淡い色を指定した時は、背景がグレーよりも白の方が見やすいです。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()
次に、平面座標(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()
最後に、等高線の高さを色で表現してみる例です。こちらもカラーマップでグラデーション含め指定できることがとても有効です。
# 等高線
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()
本記事のコード
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