LoginSignup
4
5

More than 1 year has passed since last update.

[matplotlib] 任意の数の色を使って色分けする

Last updated at Posted at 2021-10-16

※ この記事を書く際に利用したコードに関連するライブラリのバージョンは以下になります.

Python: 3.9.7
matplotlib:  3.4.2
numpy:  1.20.3

要点だけまとめ

色分けで使いたい色の数に応じた対応:

  • 3~5色程度で色分けしたい: 手動でラベルから色に対応する配列を作る.
  • ~20色: matplotlib.tab10matplotlib.tab20などを使う.
  • 20色以上: matplotlib.colors.CSS4_COLORSを使う.

クラスタやカテゴリごとに色分けしたい

使う場面

以下のように,散布図の点たちをクラスタごとに(もしくは,クラスタに限らず,何らかの条件で)色分けしたいようなケースを考えます.
image.png

クラスタ数が3など小さい場合は,label2color = ['r', 'g', 'b']のように設定して,以下のような関数を使えばよいです.

クラスタごとに点を色分けしてプロットする
def plot_points(d, label2color):
  fig, ax = plt.subplots(figsize=(8, 8))
  for i in range(len(d)):
    # d[i]: クラスタiに属する点[x,y]のリスト
    ax.scatter(d[i][:, 0], d[i][:, 1], s=6,
              c=label2color[i], label=i) # ここの引数cで色を設定している
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.legend(fontsize=12, prop={'size':24}, 
            loc='center left', bbox_to_anchor=(1,0.5), 
            markerscale=10)
  plt.show()

しかし,クラスタ数が多くなってくると,手動でlabel2colorのような配列を設定するのは骨が折れます.

この記事で説明すること

この記事では,任意の数の色で色分けする方法について説明します.
結論を述べると,10色~20色ほど使いたい場合,matplotlib.cm.tab10matplotlib.cm.tab20などのカラーマップが用意されているのでそれを使えばいいです.
また,それ以上の数の異なる色を使いたい場合は,matplotlib.colors.CSS4_COLORSを使うと良いかと思います.

~20色程度の色を使いたい場合

この場合は,matplotlib.cm.tab10matplotlib.cm.tab20を使うとよいです.
例えば,上で示したコード中のax.scatter()において,引数c=matplotlib.cm.tab20(i) (iはクラスタの番号)のように設定します.
すると,さきほど手動で3色分定義していた,label2colorのような配列を定義しなくても自動で色分けしてくれます.

tab20を使って色分けしてプロットする
def plot_points_tab(d):
  fig, ax = plt.subplots(figsize=(8, 8))
  for i in range(len(d)):
    ax.scatter(d[i][:, 0], d[i][:, 1], s=6,
              c=matplotlib.cm.tab20(i), label=i) 
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.legend(fontsize=12, prop={'size':24}, 
            loc='center left', bbox_to_anchor=(1,0.5), 
            markerscale=10)
  plt.show()

クラスタ数=20として点列を生成して,上の関数を利用してプロットすると以下のようになります.
20個のクラスタが異なる色で色分けされていることがわかります(結構似ている色もありますが).
image.png

20色以上程度の色を使いたい場合

先ほど使っていたmatplotlib.cm.tab20は20色しか用意されていないので,それ以上の数の色を使いたい場合は違う方法を取らないといけません.

matplotlib.colors.CSS4_COLORSについて

そこで,今回は matplotlib.colors.CSS4_COLORS を使う方法を紹介します.
matplotlib.colors.CSS4_COLORSでは148色の色が定義されています.

matplotlib.colors.CSS4_COLORSについて確認
print(type(matplotlib.colors.CSS4_COLORS)) # >> <class 'dict'>
print(len(matplotlib.colors.CSS4_COLORS))  # >> 148

つまり,matplotlib.colors.CSS4_COLORSは辞書型で148個の要素からなることがわかります.
実際の中身は,以下のように,キー = 利用できる色名,値 = 対応するカラーコード として格納されています.
{'aliceblue': '#F0F8FF', 'antiquewhite': '#FAEBD7', 'aqua': '#00FFFF', 'aquamarine': '#7FFFD4', 'azure': '#F0FFFF', 'beige': '#F5F5DC', 'bisque': '#FFE4C4', 'black': '#000000', ...

ランダムに任意の数のカラーコードを取得してリストにする

今回は,必要な数だけカラーコードを取得するために,この辞書からランダムに抽出を行います.
それを行う関数を以下に示します.

任意の数のカラーコードを生成する関数
def choose_colors(num_colors):
  # matplotlib.colors.CSS4_COLORSの値だけをリストにする
  tmp = list(matplotlib.colors.CSS4_COLORS.values())
  # リストにしたものをランダムにシャッフルする
  random.shuffle(tmp)
  # 必要な数だけ先頭から取り出してreturnする
  label2color = tmp[:num_colors]
  return label2color

この関数 choose_colors() を使えば,自動で各ラベルに対応する色のリストを作ることができます.
つまり,冒頭で示したような,ラベルと色の対応を表すリストlabel2colorが,任意のサイズで作れることになります.
実際に,この関数 choose_colors() と冒頭のプロット用の関数 plot_points() を使って,クラスタ数=30でプロットしてみると以下のようになりました.

image.png

ほとんど見分けがつかないが微妙に違う色(25番と28番など)がありますが,この辺を解決するのは難しそう...

[追記]
クラスタの数が多い場合,凡例を横に出しておくと見づらいです.
以下のように,クラスタの中心にラベルを記載しておくことで多少はマシになると思います(コメント頂いた方ありがとうございました).

image.png

クラスタ中心にラベルを記載してプロットする関数
def plot_points_annotated(d, label2color):
  fig, ax = plt.subplots(figsize=(8, 8))
  for i in range(len(d)):
    ax.scatter(d[i][:, 0], d[i][:, 1], s=6,
              c=label2color[i], label=i)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    # 各クラスタの中心にラベルを記載
    ax.annotate(i,
              xy=tuple(np.mean(d[i], axis=0)), fontsize=10, color='k',
              bbox={'facecolor':label2color[i], 'edgecolor':'k', 'alpha':0.8})
  plt.show()

ちなみに148色以上使いたい場合(そんなことなかなかなさそうですが)は,matplotlib.colors.XKCD_COLORSというものがあり,こちらは949色使えるそうです.

参考

matplotlibで色をたくさん使う

4
5
2

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
4
5