matplotlibでTableau風の色を使う

滅多なことでは使う機会がないと思うのですが、matplotlibで使える色名の中に、
Tableauのカラーパレット(Tableau 10)の色を指定するものがあるのを見つけたので紹介します。

参考:matplotlib.colors
こちらのページにひっそりと次の記載があります。

one of the Tableau Colors from the ‘T10’ categorical palette (the default color cycle): {‘tab:blue’, ‘tab:orange’, ‘tab:green’, ‘tab:red’, ‘tab:purple’, ‘tab:brown’, ‘tab:pink’, ‘tab:gray’, ‘tab:olive’, ‘tab:cyan’} (case-insensitive);

定数も用意されているのでそれを確認してみましょう。


import matplotlib.pyplot as plt
import matplotlib.colors as mcolors

mcolors.TABLEAU_COLORS
'''
OrderedDict([('tab:blue', '#1f77b4'),
             ('tab:orange', '#ff7f0e'),
             ('tab:green', '#2ca02c'),
             ('tab:red', '#d62728'),
             ('tab:purple', '#9467bd'),
             ('tab:brown', '#8c564b'),
             ('tab:pink', '#e377c2'),
             ('tab:gray', '#7f7f7f'),
             ('tab:olive', '#bcbd22'),
             ('tab:cyan', '#17becf')])
'''

matplotlibで色を指定する部分に”tab:blue”と入れてやればいつも見慣れたTableauの青が表示されます。
(“tab:olive”は何か違うような気がするのですが僕の環境のせいでしょうか)

せっかくなので、10本の棒グラフを用意して使ってみましょう。


x = range(1, 11)
y = range(10, 0, -1)
fig = plt.figure()
ax = fig.add_subplot(111, title="Tableau Colors")
ax.bar(x, y, color=mcolors.TABLEAU_COLORS)
plt.show()

出力はこちら。

matplotlibのグラフ間の間隔の調整

普段の分析でもこのブログでも、matplotlibの一つのfigureに複数のグラフを描写することがよくあります。

その時、稀に困るのがタイトルやラベルが他のグラフに重なってしまう時です。
それ以外にも微妙に感覚が詰まりすぎてたり広すぎたりで見た目が悪いなぁと思うことがあります。

その場合、subplots_adjustを使って、間隔を調整できます。
ドキュメントはこちら。
matplotlib.pyplot.subplots_adjust
引数の意味はこちらにもあります。
matplotlib.figure.SubplotParams

次の6種類の引数を渡せますが、間隔の調整に使うのは、hspaceとwspaceです。

The parameter meanings (and suggested defaults) are:

left = 0.125 # the left side of the subplots of the figure
right = 0.9 # the right side of the subplots of the figure
bottom = 0.1 # the bottom of the subplots of the figure
top = 0.9 # the top of the subplots of the figure
wspace = 0.2 # the amount of width reserved for space between subplots,
# expressed as a fraction of the average axis width
hspace = 0.2 # the amount of height reserved for space between subplots,
# expressed as a fraction of the average axis height
Copy to clipboard
The actual defaults are controlled by the rc file

無理やり作った例で恐縮ですが、調整せずにグラフ間で重なってしまった例と、
subplots_adjustで調整した例を作りました。


import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [1, 10, 100, 1000, 10000]
# 悪い例
fig = plt.figure(figsize=(9, 6),  facecolor="white")
for i in range(3):
    for j in range(3):
        ax = fig.add_subplot(3, 3, 1 + j + 3*i)
        ax.set_title("複数行の\nタイトル")
        ax.plot(x, y)
plt.show()
# 間隔を調整した例
fig = plt.figure(figsize=(9, 6),  facecolor="white")
fig.subplots_adjust(hspace=0.6, wspace=0.4)
for i in range(3):
    for j in range(3):
        ax = fig.add_subplot(3, 3, 1 + j + 3*i)
        ax.set_title("複数行の\nタイトル")
        ax.plot(x, y)
plt.show()

出力はそれぞれこちらです。

hspace=0.6 と wspace=0.4 の値ですが、これはドキュメント読んで何かしら計算して決めるより、
適当な値を入れて何度か試すのがおすすめです。
初期値はそれぞれ0.2なので、それより大きい値を入れると広くなります。

matplotlibでバイオリン図

データの可視化方法として、バイオリン図というものがあります。
バイオリン図 – Wikipedia

pythonでこれを書こうと思ったら、 Seaborn を使うのが定番なのですが、
実はmatplotlibにもAPIが用意されていたことを知ったのでその紹介です。

ドキュメント
matplotlib.axes.Axes.violinplot
(ただ、どうも Seaborn の方が使いやすそう。)

とりあえず動かしてみましょう。データは手頃なところで、 iris の4つの特徴量を可視化してみます。


import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
data = load_iris().data
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, title="iris data")
ax.violinplot(data)
plt.show()

出力はこちら。

先ほどのドキュメントに記載されている通り、他にも細かなオプションで見た目が調整できるのですが、
Seaborn の方が多機能のようです。
バイオリンの左右に違う分布を表示するといったことを行いたかったのですが、
どうやらmatplotlibではできなさそう。

matplotlibで折れ線グラフ(plot)を書く時に線の書式を指定する

matplotlibで折れ線グラフを書く時に線の書式を指定する方法のメモです。
大抵のケースでは色で見分ければ十分なのですが、たまに点線や破線を使いたいことがあります。
(色が使えない場合もマーカーで見分けてもいいのですけどね。)

ドキュメントはこちらです。
set_linestyle(ls)
matplotlib.pyplot.plot の linestyle のリンクをクリックすると上のページに飛びます。

方法は簡単で、 plot する時に linestyle変数に ‘dashed’ などの文字列や ‘:’ などの記号を指定するだけです。
Noneで、線を消すこともできます。(その場合はマーカーを使いましょう)

試しに4種類の線を引いてみました。
(線の種類の区別を目立たさせるため、色は揃えました。)


import matplotlib.pyplot as plt
import numpy as np

# データ生成
x = np.arange(10)
y0 = np.random.normal(0, 0.5, 10)
y1 = np.random.normal(1, 0.5, 10)
y2 = np.random.normal(2, 0.5, 10)
y3 = np.random.normal(3, 0.5, 10)

plt.rcParams["font.size"] = 14
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(1, 1, 1, title="linestyleの例")
ax.plot(x, y0, linestyle="-", c="b", label="linestyle : solid, '-'")
ax.plot(x, y1, linestyle="--", c="b", label="linestyle : dashed, '--'")
ax.plot(x, y2, linestyle="-.", c="b", label="linestyle : dashdot, '-.''")
ax.plot(x, y3, linestyle=":", c="b", label="linestyle : dotted, ':''")
ax.legend(bbox_to_anchor=(1.05, 1))
plt.show()

出力はこちら。

matplotlibのデフォルトのフォントを変更する

前の記事でmatplotlibで日本語を表示できるフォントをインストールしましたので、
この記事では実際にそのフォントを使う方法を書いておきます。

最初に、デフォルトのフォントのままだと、グラフがどのように表示されるのかを見ておきましょう。


import matplotlib.pyplot as plt
# デフォルトの設定を確認
print(plt.rcParams["font.family"]) # => ['sans-serif']
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10),range(10), label="データ1")
ax.plot(range(10),range(0,20,2), label="データ2")
ax.set_title("タイトル")
ax.set_xlabel("x軸のラベル")
ax.set_ylabel("y軸のラベル")
ax.legend()
plt.show()

こちらのコードを実行した結果がこの画像です。日本語文字が豆腐のようになります。

これを回避する方法の一つは実行するたびにフォントを指定することです。
このように、font.familyを指定することで、日本語の文字も豆腐にならず表示されます。


import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "IPAexGothic"

このように指定したあとに、上と同じプログラムを実行すると、下図のように正しく日本語が表示されます。

ただし、これは毎回書くのは結構面倒です。たった1行なのに。
そこで、対応としてmatplotlibの設定ファイルでフォントを指定します。

最初に下記のコードを実行して、設定ファイルの場所を確認します。


>>> import matplotlib
>>> print(matplotlib.matplotlib_fname()) 

環境によって結果は変わりますが、自分の場合は下記の場所にありました。
/Users/<ユーザー名>/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages/matplotlib/mpl-data/matplotlibrc

このmatplotlibrcのバックアップを取って編集します。
ファイル内に下記の記載があるのでコメントアウトを解除してIPAexGothicを指定します。
元の記述
#font.family : sans-serif
修正後
font.family : IPAexGothic

これで次回以降はフォントの指定をしなくてもmatplotlibで日本語が使えます。

もしうまく表示されない場合はキャッシュファイルを一度削除する必要があります。
matplotlib.get_cachedir()
でキャッシュのディレクトリがわかるので、ここにあるファイルを消して試してみてください。

MacにIPAフォントをインストールする

MacにIPAフォントをインストールする手順のメモです。
データサイエンティストがフォントをインストールする目的はおそらく一つしかないと思うのですが、
この作業の目的は、pythonのグラフ描画ライブラリである、matplotlibで作成したグラフ中で日本語を使うためです。

もともとAppleGothicというのが入っているので、それを使ってもいいのですが、
「ー」や「数」など、かなり使用頻度の高い文字が対応していなかったりするので、IPAのフォントをインストールします。

配布元サイト
ダウンロードページ
インストール方法

それでは順番にやっていきましょう。

最初にダウンロードページからフォントファイルをダウンロードします。
ゴシックの方だけあれば十分ですが、せっかくなので
2書体パック(IPAex明朝(Ver.003.01)、IPAexゴシック(Ver.003.01))
を選びました。

ダウンロードしたzipファイルを解答すると中に次の2ファイルと、ライセンス関係のテキストファイルがあります。
ipaexg.ttf
ipaexm.ttf

この2ファイルを
/Library/Fonts
にコピーしたらインストール完了です。

Mac には、Font Book というアプリケーションがあり、インストールされているフォントを確認できますが、
この中に
IPAexゴシックと、IPAex明朝 というのが登場していれば成功です。
フォントを選択して、[i]マークを押すと、詳細な情報が見れます。
この中の、PostScript名 に入っている
IPAexGothic や、 IPAexMincho が、matplotlibに設定するときの名前なのでメモしておきましょう。

matplotlibで等高線

折れ線グラフや散布図に比べると利用頻度が落ちますが、
2次元から1次元への写像の可視化として等高線を使うことがあるので、そのメモです。

使う関数は、線を引く場合は、contour,色を塗る場合は contourf を使います。

サンプルの関数は何でもいいのですが、今回はこれを使います。
$$
1-\exp(-x^2+2xy-2y^2)
$$
まずはデータの準備です。


import matplotlib.pyplot as plt
import numpy as np

# 関数の定義
def f(x, y):
    return 1- np.exp(-x**2 + 2*x*y - 2*y**2) 

# プロットする範囲のmeshgridを作成する。
X = np.linspace(-2,2,41)
Y = np.linspace(-2,2,41)
xx, yy = np.meshgrid(X, Y)

そして可視化してみます。まずは等高線から。


fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.contour(xx,yy,f(xx, yy))
plt.show()

次に、色を塗る場合。


fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.contourf(xx,yy,f(xx, yy), alpha=0.5)
plt.show()

色の指定などをきちんとしていないのですが、まあまあみやすく可視化できていますね。
機械学習の決定境界の可視化などでも、これと同じ方法を使うことがあります。