Matplotlib дискретная цветовая панель
Я пытаюсь сделать дискретную цветовую полосу для диаграммы рассеяния в matplotlib
у меня есть данные x, y и для каждой точки целочисленное значение тега, которое я хочу представить уникальным цветом, например
plt.scatter(x, y, c=tag)
обычно тег будет целым числом в диапазоне от 0-20, но точный диапазон может измениться
до сих пор я только что использовал настройки по умолчанию, например
plt.colorbar()
что дает непрерывный спектр цветов. В идеале я хотел бы набор из n дискретные цвета (n=20 в этом примере). Еще лучше было бы получить значение тега 0 для получения серого цвета и 1-20 быть красочным.
Я нашел несколько сценариев "поваренной книги", но они очень сложны, и я не могу думать, что они являются правильным способом решения, казалось бы, простой проблемы
5 ответов:
вы можете создать пользовательскую дискретную цветовую панель довольно легко, используя BoundaryNorm в качестве нормализатора для вашего разброса. Причудливый бит (в моем методе) делает 0 шоу как серый.
для изображений я часто использую cmap.set_bad () и конвертировать мои данные в массив NumPy маскируется. Это было бы намного проще сделать 0 серым, но я не мог заставить это работать с разбросом или пользовательским cmap.
в качестве альтернативы вы можете сделать свой собственный cmap с нуля или считывать существующий и переопределить только некоторые конкретные записи.
# setup the plot fig, ax = plt.subplots(1,1, figsize=(6,6)) # define the data x = np.random.rand(20) y = np.random.rand(20) tag = np.random.randint(0,20,20) tag[10:12] = 0 # make sure there are some 0 values to showup as grey # define the colormap cmap = plt.cm.jet # extract all colors from the .jet map cmaplist = [cmap(i) for i in range(cmap.N)] # force the first color entry to be grey cmaplist[0] = (.5,.5,.5,1.0) # create the new map cmap = cmap.from_list('Custom cmap', cmaplist, cmap.N) # define the bins and normalize bounds = np.linspace(0,20,21) norm = mpl.colors.BoundaryNorm(bounds, cmap.N) # make the scatter scat = ax.scatter(x,y,c=tag,s=np.random.randint(100,500,20),cmap=cmap, norm=norm) # create a second axes for the colorbar ax2 = fig.add_axes([0.95, 0.1, 0.03, 0.8]) cb = mpl.colorbar.ColorbarBase(ax2, cmap=cmap, norm=norm, spacing='proportional', ticks=bounds, boundaries=bounds, format='%1i') ax.set_title('Well defined discrete colors') ax2.set_ylabel('Very custom cbar [-]', size=12)
Я лично думаю, что с 20 различными цветами его немного трудно прочитать конкретное значение, но это зависит от вас, конечно.
вы могли бы следовать этому пример:
#!/usr/bin/env python """ Use a pcolor or imshow with a custom colormap to make a contour plot. Since this example was initially written, a proper contour routine was added to matplotlib - see contour_demo.py and http://matplotlib.sf.net/matplotlib.pylab.html#-contour. """ from pylab import * delta = 0.01 x = arange(-3.0, 3.0, delta) y = arange(-3.0, 3.0, delta) X,Y = meshgrid(x, y) Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1) Z = Z2 - Z1 # difference of Gaussians cmap = cm.get_cmap('PiYG', 11) # 11 discrete colors im = imshow(Z, cmap=cmap, interpolation='bilinear', vmax=abs(Z).max(), vmin=-abs(Z).max()) axis('off') colorbar() show()
которая производит следующим образом:
чтобы установить значения выше или ниже диапазона цветовой карты, вы хотите использовать
set_over
иset_under
методы цветовой карты. Если вы хотите пометить определенное значение, замаскируйте его (т. е. создайте маскированный массив) и используйтеset_bad
метод. (Посмотрите документацию для базового класса colormap:http://matplotlib.org/api/colors_api.html#matplotlib.colors.Colormap)похоже, вы хотите что-то вроде это:
import matplotlib.pyplot as plt import numpy as np # Generate some data x, y, z = np.random.random((3, 30)) z = z * 20 + 0.1 # Set some values in z to 0... z[:5] = 0 cmap = plt.get_cmap('jet', 20) cmap.set_under('gray') fig, ax = plt.subplots() cax = ax.scatter(x, y, c=z, s=100, cmap=cmap, vmin=0.1, vmax=z.max()) fig.colorbar(cax, extend='min') plt.show()
приведенные выше ответы хороши, за исключением того, что они не имеют правильного размещения тиков на цветовой панели. Мне нравится иметь Тики в середине цвета, чтобы число - > цветовое отображение было более четким. Вы можете решить эту проблему, изменив пределы вызова matshow:
import matplotlib.pyplot as plt import numpy as np def discrete_matshow(data): #get discrete colormap cmap = plt.get_cmap('RdBu', np.max(data)-np.min(data)+1) # set limits .5 outside true range mat = plt.matshow(data,cmap=cmap,vmin = np.min(data)-.5, vmax = np.max(data)+.5) #tell the colorbar to tick at integers cax = plt.colorbar(mat, ticks=np.arange(np.min(data),np.max(data)+1)) #generate data a=np.random.randint(1, 9, size=(10, 10)) discrete_matshow(a)
Я думаю, что вы хотели бы посмотреть на цвета.ListedColormap чтобы создать свою цветовую карту, или если вам просто нужна статическая цветовая карта, над которой я работал приложение что может помочь.