Jaki jest trywialny przykład generowania losowych kolorów do przekazania do funkcji kreślących?
Nazywam rozproszenie wewnątrz pętli i chcę, aby każdy wykres miał inny kolor.
for X,Y in data:
scatter(X, Y, c=??)
c: kolor. c może być pojedynczym ciągiem formatu koloru, sekwencją specyfikacji kolorów o długości N lub sekwencją N liczb, które mają być odwzorowane na kolory przy użyciu cmap i normy określonych za pomocą kwargs (patrz poniżej). Zwróć uwagę, że c nie powinno być pojedynczą numeryczną sekwencją RGB lub RGBA, ponieważ jest ona nie do odróżnienia od tablicy wartości, które mają zostać zmapowane. c może być jednak tablicą 2-D, w której wiersze to RGB lub RGBA.
python
matplotlib
John Mee
źródło
źródło
Odpowiedzi:
Na tej podstawie i na twojej odpowiedzi: Wydaje mi się, że faktycznie chcesz mieć
n
różne kolory dla swoich zbiorów danych; chcesz odwzorować indeksy liczb całkowitych0, 1, ..., n-1
na różne kolory RGB. Coś jak:Oto funkcja, aby to zrobić:
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)
Wykorzystanie we fragmencie pseudokodu w pytaniu:
cmap = get_cmap(len(data)) for i, (X, Y) in enumerate(data): scatter(X, Y, c=cmap(i))
Wygenerowałem liczbę w mojej odpowiedzi za pomocą następującego kodu:
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()
Przetestowano zarówno z Pythonem 2.7 i matplotlib 1.5, jak iz Pythonem 3.5 i matplotlib 2.0. Działa zgodnie z oczekiwaniami.
źródło
for X,Y in data: scatter(X, Y, c=numpy.random.rand(3,))
źródło
color=(random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1))
scatter(X,Y, c=numpy.random.rand(len(X),3)
opracowując odpowiedź @ john-mee, jeśli masz dowolnie długie dane, ale nie potrzebujesz ściśle unikalnych kolorów:
dla pythona 2:
from itertools import cycle cycol = cycle('bgrcmk') for X,Y in data: scatter(X, Y, c=cycol.next())
dla pythona 3:
from itertools import cycle cycol = cycle('bgrcmk') for X,Y in data: scatter(X, Y, c=next(cycol))
Ma to tę zaletę, że kolory są łatwe do kontrolowania i krótkie.
źródło
Przez pewien czas byłem naprawdę zirytowany faktem, że matplotlib nie generuje map kolorów z przypadkowymi kolorami, ponieważ jest to powszechna potrzeba segmentacji i grupowania zadań.
Po prostu generując przypadkowe kolory, możemy zakończyć z niektórymi, które są zbyt jasne lub zbyt ciemne, co utrudnia wizualizację. Ponadto zwykle potrzebujemy, aby pierwszy lub ostatni kolor był czarny, reprezentujący tło lub wartości odstające. Napisałem więc małą funkcję do mojej codziennej pracy
Oto jego zachowanie:
new_cmap = rand_cmap(100, type='bright', first_color_black=True, last_color_black=False, verbose=True)
Niż po prostu użyj new_cmap jako mapy kolorów na matplotlib:
ax.scatter(X,Y, c=label, cmap=new_cmap, vmin=0, vmax=num_labels)
Kod jest tutaj:
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
Jest również na github: https://github.com/delestro/rand_cmap
źródło
Gdy mniej niż 9 zbiorów danych:
colors = "bgrcmykw" color_index = 0 for X,Y in data: scatter(X,Y, c=colors[color_index]) color_index += 1
źródło
Skoro pytanie brzmi
How to generate random colors in matplotlib?
i jak szukałem odpowiedzi w sprawiepie plots
, myślę, że warto tu umieścić odpowiedź (dlapies
)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()
Wynik
źródło
Oto bardziej zwięzła wersja odpowiedzi Ali, podająca jeden odrębny kolor na działkę:
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))
źródło
Na podstawie odpowiedzi Ali i Champitoad:
Jeśli chcesz wypróbować różne palety dla tego samego, możesz to zrobić w kilku wierszach:
cmap=plt.cm.get_cmap(plt.cm.viridis,143)
^ 143 to liczba kolorów, które próbujesz
Wybrałem 143, ponieważ w grę wchodzi cała gama kolorów na mapie kolorów. To, co możesz zrobić, to próbkować n-ty kolor w każdej iteracji, aby uzyskać efekt mapy kolorów.
n=20 for i,(x,y) in enumerate(points): plt.scatter(x,y,c=cmap(n*i))
źródło
Poprawa odpowiedzi https://stackoverflow.com/a/14720445/6654512 do pracy z Python3. Ten fragment kodu czasami generował liczby większe niż 1, a matplotlib generował błąd.
for X,Y in data: scatter(X, Y, c=numpy.random.random(3))
źródło
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])
źródło
Jeśli chcesz mieć pewność, że kolory są wyraźne - ale nie wiesz, ile kolorów potrzeba. Spróbuj czegoś takiego. Wybiera kolory z przeciwnych stron spektrum i systematycznie zwiększa ziarnistość.
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()
wynik
Podziękowania dla @Ali za zapewnienie podstawowej implementacji.
źródło