Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
129
Help us understand the problem. What is going on with this article?
@kenmatsu4

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

More than 5 years have passed since last update.

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

129
Help us understand the problem. What is going on with this article?
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
kenmatsu4
Kaggle Master (https://www.kaggle.com/kenmatsu4) データ解析的なことや、統計学的なこと、機械学習などについて書いています。 【今まで書いた記事一覧】http://qiita.com/kenmatsu4/items/623514c61166e34283bb 【English Blog】 http://kenmatsu4.tumblr.com

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
129
Help us understand the problem. What is going on with this article?