matplotlib에서 임의의 색상을 생성하는 방법은 무엇입니까?


87

플로팅 함수에 전달하기 위해 임의의 색상을 생성하는 방법에 대한 간단한 예는 무엇입니까?

루프 내부에서 산란을 호출하고 각 플롯에 다른 색상을 지정하고 싶습니다.

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

답변:


141

루프 내부에서 산란을 호출하고 각 플롯을 다른 색상으로 원합니다.

그것을 바탕으로, 그리고 당신의 대답에 따르면 : 당신은 실제로 당신의 데이터 셋에 대해 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()

Python 2.7 및 matplotlib 1.5와 Python 3.5 및 matplotlib 2.0으로 테스트되었습니다. 예상대로 작동합니다.


1
@ user1941407 감사합니다! :) 누군가 익명으로 답변에 반대하는 이유를 알았 으면합니다.
알리

7
어쩌면 그것은 복잡
잉그리드

1
작동하지 않는 것 같습니까? 파이썬 콘솔에 전혀 연결되지 않는 것 같습니다.
mjwrazor

@mjwrazor 죄송합니다. "작동하지 않는"항목을 자세히 설명해 주시겠습니까?
Ali

나는 파이썬 콘솔에 메서드를 배치하려고했지만 콘솔은 그것을 읽지 않습니다. 또한 메서드의 끝에있는 논리는 의미가 없습니다. 실행 메서드를 반환하는 다른 메서드를 호출하는 메서드를 반환하는 이유. 실행 된 메서드를 반환하지 않는 이유는 무엇입니까?
mjwrazor

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

1
플로팅 할 값이 세 개이면 어떨까요?
panda-34

1
3은 R, G 및 B 성분의 3 가지 값을 의미합니까?
Kshitij Bajracharya

numpy없이 사용할 수 있습니다color=(random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1))
azzamsa

2
더 효율적이고 적은 입력 :scatter(X,Y, c=numpy.random.rand(len(X),3)
Qualia

31

임의의 긴 데이터가 있지만 엄격하게 고유 한 색상이 필요하지 않은 경우 @ john-mee의 대답을 정교하게 설명합니다.

파이썬 2 :

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

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

파이썬 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
감사. 매우 유용했습니다.
Ash

15

데이터 세트가 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여기에 답변을 넣을 가치가 있다고 생각합니다 (for 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
이봐 요,이게 바로 제가 찾고있는 것입니다. 그러나 두 번째 사진 (나에게도 이런 일이 발생 함)에서는 거의 동일한 색상 (베이지 / 화이트)을 얻습니다. 이 접근 방식을 사용할 수 있지만 더 뚜렷한 색상을 선택하는 방식으로 샘플링 할 수 있습니까?
armara 19

9

다음은 플롯 당 하나의 뚜렷한 색상을 제공하는 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])

그래프를 그릴 때의 색상이 색상리스트를 할당
산토 Magadum에게

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.