matplotlibでランダムな色を生成する方法は?


83

プロット関数に渡すためのランダムな色を生成する方法の簡単な例は何ですか?

ループ内でスキャッターを呼び出しており、各プロットに異なる色を使用したいと考えています。

for X,Y in data:
   scatter(X, Y, c=??)

c:色。cは、単一の色フォーマット文字列、長さNの色指定のシーケンス、またはkwargsを介して指定されたcmapとnormを使用して色にマップされるN個の数値のシーケンスです(以下を参照)。cは、カラーマップされる値の配列と区別がつかないため、単一の数値RGBまたはRGBAシーケンスであってはならないことに注意してください。cは、行がRGBまたはRGBAである2次元配列にすることができます。


1
何からランダムに選ばれましたか?利用可能なすべての色からランダムに選択すると、いくつかの非常に異なる色と、区別が難しいほど類似した色の奇妙な組み合わせが得られる場合があります。
BrenBarn 2013

回答:


139

ループ内でスキャッターを呼び出しており、各プロットを異なる色にしたい。

それとあなたの答えに基づいて:あなたは実際にあなたのデータセットにn 異なる色を望んでいるようです。整数インデックス0, 1, ..., n-1を個別のRGBカラーにマップする必要があります。何かのようなもの:

インデックスを色にマッピング

これを行う関数は次のとおりです。

import matplotlib.pyplot as plt

def get_cmap(n, name='hsv'):
    '''Returns a function that maps each index in 0, 1, ..., n-1 to a distinct 
    RGB color; the keyword argument name must be a standard mpl colormap name.'''
    return plt.cm.get_cmap(name, n)

質問の疑似コードスニペットでの使用法:

cmap = get_cmap(len(data))
for i, (X, Y) in enumerate(data):
   scatter(X, Y, c=cmap(i))

私は次のコードで私の答えの図を生成しました:

import matplotlib.pyplot as plt

def get_cmap(n, name='hsv'):
    '''Returns a function that maps each index in 0, 1, ..., n-1 to a distinct 
    RGB color; the keyword argument name must be a standard mpl colormap name.'''
    return plt.cm.get_cmap(name, n)

def main():
    N = 30
    fig=plt.figure()
    ax=fig.add_subplot(111)   
    plt.axis('scaled')
    ax.set_xlim([ 0, N])
    ax.set_ylim([-0.5, 0.5])
    cmap = get_cmap(N)
    for i in range(N):
        rect = plt.Rectangle((i, -0.5), 1, 1, facecolor=cmap(i))
        ax.add_artist(rect)
    ax.set_yticks([])
    plt.show()

if __name__=='__main__':
    main()

Python2.7とmatplotlib1.5の両方、およびPython3.5とmatplotlib2.0の両方でテストされています。期待どおりに動作します。


1
@ user1941407ありがとう!:)なぜ誰かが匿名で答えに反対票を投じたのかを知っていたらいいのにと思います。
アリ

7
多分それは複雑です
ingrid 2016

1
うまくいかないようですか?Pythonコンソールにまったく接続されていないようです。
mjwrazor 2017年

@mjwrazor申し訳ありませんが、フォローしていません。「うまくいかない」ことを詳しく教えてください。
アリ

メソッドをPythonコンソールに配置しようとしましたが、コンソールがそれを読み込むことはありません。また、メソッドの最後にあるロジックは意味がありません。実行メソッドを返す別のメソッドを呼び出すメソッドを返す理由。実行されたメソッドを返さないのはなぜですか?
mjwrazor 2017年

76
for X,Y in data:
   scatter(X, Y, c=numpy.random.rand(3,))

1
プロットする値が3つある場合はどうなりますか?
パンダ-34

1
3はR、G、Bコンポーネントの3つの値を表しますか?
KshitijBajracharya19年1

numpyのなしでは、使用することができますcolor=(random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1))
azzamsa

1
より効率的でタイピングが少ない:scatter(X,Y, c=numpy.random.rand(len(X),3)
クオリア

31

@ john-meeの答えを詳しく説明します。任意の長さのデータがあるが、厳密に一意の色は必要ない場合:

Python 2の場合:

from itertools import cycle
cycol = cycle('bgrcmk')

for X,Y in data:
    scatter(X, Y, c=cycol.next())

Python 3の場合:

from itertools import cycle
cycol = cycle('bgrcmk')

for X,Y in data:
    scatter(X, Y, c=next(cycol))

これには、色の制御が簡単で、短いという利点があります。


27

しばらくの間、matplotlibがランダムな色のカラーマップを生成しないという事実に本当に悩まされていました。これは、セグメンテーションおよびクラスタリングタスクの一般的なニーズであるためです。

ランダムな色を生成するだけでは、明るすぎたり暗すぎたりして、視覚化が困難になる場合があります。また、通常、最初または最後の色を黒にして、背景または外れ値を表す必要があります。だから私は日常の仕事のために小さな関数を書きました

動作は次のとおりです。

new_cmap = rand_cmap(100, type='bright', first_color_black=True, last_color_black=False, verbose=True)

生成されたカラーマップ

matplotlibのカラーマップとしてnew_cmapを使用するよりも:

ax.scatter(X,Y, c=label, cmap=new_cmap, vmin=0, vmax=num_labels)

コードはここにあります:

def rand_cmap(nlabels, type='bright', first_color_black=True, last_color_black=False, verbose=True):
    """
    Creates a random colormap to be used together with matplotlib. Useful for segmentation tasks
    :param nlabels: Number of labels (size of colormap)
    :param type: 'bright' for strong colors, 'soft' for pastel colors
    :param first_color_black: Option to use first color as black, True or False
    :param last_color_black: Option to use last color as black, True or False
    :param verbose: Prints the number of labels and shows the colormap. True or False
    :return: colormap for matplotlib
    """
    from matplotlib.colors import LinearSegmentedColormap
    import colorsys
    import numpy as np


    if type not in ('bright', 'soft'):
        print ('Please choose "bright" or "soft" for type')
        return

    if verbose:
        print('Number of labels: ' + str(nlabels))

    # Generate color map for bright colors, based on hsv
    if type == 'bright':
        randHSVcolors = [(np.random.uniform(low=0.0, high=1),
                          np.random.uniform(low=0.2, high=1),
                          np.random.uniform(low=0.9, high=1)) for i in xrange(nlabels)]

        # Convert HSV list to RGB
        randRGBcolors = []
        for HSVcolor in randHSVcolors:
            randRGBcolors.append(colorsys.hsv_to_rgb(HSVcolor[0], HSVcolor[1], HSVcolor[2]))

        if first_color_black:
            randRGBcolors[0] = [0, 0, 0]

        if last_color_black:
            randRGBcolors[-1] = [0, 0, 0]

        random_colormap = LinearSegmentedColormap.from_list('new_map', randRGBcolors, N=nlabels)

    # Generate soft pastel colors, by limiting the RGB spectrum
    if type == 'soft':
        low = 0.6
        high = 0.95
        randRGBcolors = [(np.random.uniform(low=low, high=high),
                          np.random.uniform(low=low, high=high),
                          np.random.uniform(low=low, high=high)) for i in xrange(nlabels)]

        if first_color_black:
            randRGBcolors[0] = [0, 0, 0]

        if last_color_black:
            randRGBcolors[-1] = [0, 0, 0]
        random_colormap = LinearSegmentedColormap.from_list('new_map', randRGBcolors, N=nlabels)

    # Display colorbar
    if verbose:
        from matplotlib import colors, colorbar
        from matplotlib import pyplot as plt
        fig, ax = plt.subplots(1, 1, figsize=(15, 0.5))

        bounds = np.linspace(0, nlabels, nlabels + 1)
        norm = colors.BoundaryNorm(bounds, nlabels)

        cb = colorbar.ColorbarBase(ax, cmap=random_colormap, norm=norm, spacing='proportional', ticks=None,
                                   boundaries=bounds, format='%1i', orientation=u'horizontal')

    return random_colormap

githubにもありますhttps//github.com/delestro/rand_cmap


2
ありがとう。とても役に立ちました。
アッシュ

14

9データセット未満の場合:

colors = "bgrcmykw"
color_index = 0

for X,Y in data:
    scatter(X,Y, c=colors[color_index])
    color_index += 1

12

質問はでHow to generate random colors in matplotlib?あり、についての答えを探していたので、pie plotsここに答えを入れる価値があると思います(のためにpies

import numpy as np
from random import sample
import matplotlib.pyplot as plt
import matplotlib.colors as pltc
all_colors = [k for k,v in pltc.cnames.items()]

fracs = np.array([600, 179, 154, 139, 126, 1185])
labels = ["label1", "label2", "label3", "label4", "label5", "label6"]
explode = ((fracs == max(fracs)).astype(int) / 20).tolist()

for val in range(2):
    colors = sample(all_colors, len(fracs))
    plt.figure(figsize=(8,8))
    plt.pie(fracs, labels=labels, autopct='%1.1f%%', 
            shadow=True, explode=explode, colors=colors)
    plt.legend(labels, loc=(1.05, 0.7), shadow=True)
    plt.show()

出力

ここに画像の説明を入力してください

ここに画像の説明を入力してください


1
ねえ、これはまさに私が探しているものです。ただし、2番目の写真(これは私にも起こります)では、ほぼ同じ色(ベージュ/白)になります。このアプローチを使用することは可能ですが、より明確な色を選択する方法でサンプリングしますか?
アルマラ

9

これは、プロットごとに1つの異なる色を与えるAliの回答のより簡潔なバージョンです。

import matplotlib.pyplot as plt

N = len(data)
cmap = plt.cm.get_cmap("hsv", N+1)
for i in range(N):
    X,Y = data[i]
    plt.scatter(X, Y, c=cmap(i))

4

AliとChampitoadの回答に基づく:

同じパレットに対して異なるパレットを試したい場合は、数行でこれを行うことができます。

cmap=plt.cm.get_cmap(plt.cm.viridis,143)

^ 143はサンプリングしている色の数です

ここではカラーマップのすべての色が関係しているので、143を選びました。できることは、反復ごとにn番目の色をサンプリングして、カラーマップ効果を取得することです。

n=20 for i,(x,y) in enumerate(points): plt.scatter(x,y,c=cmap(n*i))



1
enter code here

import numpy as np

clrs = np.linspace( 0, 1, 18 )  # It will generate 
# color only for 18 for more change the number
np.random.shuffle(clrs)
colors = []
for i in range(0, 72, 4):
    idx = np.arange( 0, 18, 1 )
    np.random.shuffle(idx)
    r = clrs[idx[0]]
    g = clrs[idx[1]]
    b = clrs[idx[2]]
    a = clrs[idx[3]]
    colors.append([r, g, b, a])

グラフの描画中にこの色リストをの色で割り当てます
SantoshMagadum19年

1

色を明確にしたい場合-ただし、必要な色の数がわからない場合。このようなものを試してください。スペクトルの反対側から色を選択し、体系的に粒度を高めます。

import math

def calc(val, max = 16):
    if val < 1:
        return 0
    if val == 1:
        return max

    l = math.floor(math.log2(val-1))    #level 
    d = max/2**(l+1)                    #devision
    n = val-2**l                        #node
    return d*(2*n-1)
import matplotlib.pyplot as plt

N = 16
cmap = cmap = plt.cm.get_cmap('gist_rainbow', N)

fig, axs = plt.subplots(2)
for ax in axs:
    ax.set_xlim([ 0, N])
    ax.set_ylim([-0.5, 0.5])
    ax.set_yticks([])

for i in range(0,N+1):
    v = int(calc(i, max = N))
    rect0 = plt.Rectangle((i, -0.5), 1, 1, facecolor=cmap(i))
    rect1 = plt.Rectangle((i, -0.5), 1, 1, facecolor=cmap(v))
    axs[0].add_artist(rect0)
    axs[1].add_artist(rect1)

plt.xticks(range(0, N), [int(calc(i, N)) for i in range(0, N)])
plt.show()

出力

基本実装を提供してくれた@Aliに感謝します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.