Matplotlib дискретная цветовая панель


Я пытаюсь сделать дискретную цветовую полосу для диаграммы рассеяния в matplotlib

у меня есть данные x, y и для каждой точки целочисленное значение тега, которое я хочу представить уникальным цветом, например

plt.scatter(x, y, c=tag)

обычно тег будет целым числом в диапазоне от 0-20, но точный диапазон может измениться

до сих пор я только что использовал настройки по умолчанию, например

plt.colorbar()

что дает непрерывный спектр цветов. В идеале я хотел бы набор из n дискретные цвета (n=20 в этом примере). Еще лучше было бы получить значение тега 0 для получения серого цвета и 1-20 быть красочным.

Я нашел несколько сценариев "поваренной книги", но они очень сложны, и я не могу думать, что они являются правильным способом решения, казалось бы, простой проблемы

5 58

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)

enter image description here

Я лично думаю, что с 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()

которая производит следующим образом:

poormans_contour

чтобы установить значения выше или ниже диапазона цветовой карты, вы хотите использовать 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

приведенные выше ответы хороши, за исключением того, что они не имеют правильного размещения тиков на цветовой панели. Мне нравится иметь Тики в середине цвета, чтобы число - > цветовое отображение было более четким. Вы можете решить эту проблему, изменив пределы вызова 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

Я думаю, что вы хотели бы посмотреть на цвета.ListedColormap чтобы создать свою цветовую карту, или если вам просто нужна статическая цветовая карта, над которой я работал приложение что может помочь.