Какой тривиальный пример того, как генерировать случайные цвета для перехода к функциям построения графиков?
Я вызываю разброс внутри цикла и хочу, чтобы каждый график был разного цвета.
for X,Y in data:
scatter(X, Y, c=??)
c: цвет. c может быть строкой формата одного цвета, или последовательностью цветовых спецификаций длины N, или последовательностью из N чисел, которые должны быть отображены в цвета с использованием cmap и нормы, указанных через kwargs (см. ниже). Обратите внимание, что c не должна быть одной числовой последовательностью RGB или RGBA, потому что она неотличима от массива значений, которые нужно сопоставить по цвету. Однако c может быть двумерным массивом, в котором строки имеют формат RGB или RGBA.
python
matplotlib
Джон Ми
источник
источник
Ответы:
На основании этого и вашего ответа: мне кажется, что вам действительно нужны
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. Работает как положено.
источник
for X,Y in data: scatter(X, Y, c=numpy.random.rand(3,))
источник
color=(random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1))
scatter(X,Y, c=numpy.random.rand(len(X),3)
разработка ответа @ 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))
Преимущество этого заключается в том, что цвета легко контролировать и они короткие.
источник
Некоторое время меня действительно раздражал тот факт, что matplotlib не генерирует палитру со случайными цветами, поскольку это обычная потребность в задачах сегментации и кластеризации.
Просто генерируя случайные цвета, мы можем получить слишком яркие или слишком темные цвета, затрудняющие визуализацию. Кроме того, обычно нам нужно, чтобы первый или последний цвет был черным, представляя фон или выбросы. Итак, я написал небольшую функцию для повседневной работы
Вот его поведение:
new_cmap = rand_cmap(100, type='bright', first_color_black=True, last_color_black=False, verbose=True)
Тогда вы просто используете new_cmap в качестве цветовой карты на matplotlib:
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
источник
Когда меньше 9 наборов данных:
colors = "bgrcmykw" color_index = 0 for X,Y in data: scatter(X,Y, c=colors[color_index]) color_index += 1
источник
Поскольку вопрос в том,
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()
Вывод
источник
Вот более краткая версия ответа Али, дающая один отличный цвет для каждого участка:
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))
источник
На основе ответа Али и Чампитоада:
Если вы хотите попробовать разные палитры для одного и того же, вы можете сделать это в несколько строк:
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))
источник
Улучшение ответа https://stackoverflow.com/a/14720445/6654512 для работы с Python3. Этот фрагмент кода иногда генерирует числа больше 1, и matplotlib выдает ошибку.
for X,Y in data: scatter(X, Y, c=numpy.random.random(3))
источник
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])
источник
Если вы хотите, чтобы цвета были различимы, но не знаете, сколько цветов нужно. Попробуйте что-нибудь подобное. Он выбирает цвета с противоположных сторон спектра и систематически увеличивает детализацию.
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 за предоставление базовой реализации.
источник