Matplotlib дискретный цветной бар
Я пытаюсь сделать дискретную панель цвета для диаграммы рассеяния в matplotlib
У меня есть данные x, y и для каждой точки значение целочисленного тега, которое я хочу представить с уникальным цветом, например
plt.scatter(x, y, c=tag)
Обычно тег будет целым числом от 0 до 20, но точный диапазон может меняться
До сих пор я только что использовал настройки по умолчанию, например
plt.colorbar()
который дает непрерывный диапазон цветов. В идеале я хотел бы иметь набор из n дискретных цветов (n = 20 в этом примере). Еще лучше было бы получить значение тега 0 для создания серого цвета и 1-20 быть красочным.
Я нашел несколько сценариев "поваренной книги", но они очень сложны, и я не могу думать, что они являются правильным способом решения, казалось бы, простой проблемы.
Ответы
Ответ 1
Вы можете легко создать собственный дискретный цветной балл, используя BoundaryNorm в качестве нормализатора для вашего разброса. Причудливый бит (в моем методе) делает вывод 0 серым.
Для изображений я часто использую cmap.set_bad() и конвертирую свои данные в массив с маской размером. Это было бы намного проще сделать 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)
![enter image description here]()
Я лично считаю, что с 20 разными цветами его немного трудно читать конкретное значение, но это, конечно же, для вас.
Ответ 2
Вы можете следовать этому example:
#!/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()
который создает следующее изображение:
![poormans_contour]()
Ответ 3
Чтобы установить значения выше или ниже диапазона цветовой палитры, вы захотите использовать методы 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()
![enter image description here]()
Ответ 4
Вышеуказанные ответы хороши, за исключением того, что у них нет правильного размещения меток на цветной панели. Мне нравится, чтобы метки были посередине цвета, так что число → цветное отображение более ясное. Вы можете решить эту проблему, изменив пределы вызова 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)
![example of discrete colorbar]()
Ответ 5
Я думаю, вам нужно взглянуть на colors.ListedColormap, чтобы сгенерировать вашу цветовую палитру, или если вам просто нужен статический цветной пакет работал над приложением, которое могло бы помочь.