Matplotlib discreta barra de colores

Estoy tratando de hacer una barra de colores discreta para un diagtwig de dispersión en matplotlib

Tengo mis datos x, y, y para cada punto, un valor de etiqueta entero que quiero que se represente con un color único, por ejemplo

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

por lo general, la etiqueta será un número entero de 0 a 20, pero el rango exacto puede cambiar

Hasta ahora solo he usado la configuración predeterminada, por ejemplo,

 plt.colorbar() 

Lo que le da una gama continua de colores. Idealmente, me gustaría un conjunto de n colores discretos (n = 20 en este ejemplo). Aún mejor sería obtener un valor de etiqueta de 0 para producir un color gris y 1-20 ser colorido.

He encontrado algunos guiones de ‘libros de cocina’ pero son muy complicados y no puedo pensar que sean la forma correcta de resolver un problema aparentemente simple.

Related of "Matplotlib discreta barra de colores"

Puede crear una barra de color discreta personalizada con bastante facilidad utilizando un BoundaryNorm como normalizador para su dispersión. El bit peculiar (en mi método) es hacer que 0 aparezca como gris.

Para las imágenes, a menudo uso el cmap.set_bad () y convierto mis datos a una matriz enmascarada numpy. Eso sería mucho más fácil de hacer 0 gris, pero no podría hacer que esto funcionara con el scatter o el cmap personalizado.

Como alternativa, puede hacer su propio cmap desde cero, o leer uno existente y anular solo algunas entradas específicas.

 import numpy as np import matplotlib as mpl import matplotlib.pylab as plt fig, ax = plt.subplots(1, 1, figsize=(6, 6)) # setup the plot x = np.random.rand(20) # define the data y = np.random.rand(20) # define the data tag = np.random.randint(0, 20, 20) tag[10:12] = 0 # make sure there are some 0 values to show up as grey cmap = plt.cm.jet # define the colormap # 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 = mpl.colors.LinearSegmentedColormap.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 = plt.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) 

introduzca la descripción de la imagen aquí

Personalmente creo que con 20 colores diferentes es un poco difícil de leer el valor específico, pero eso depende de usted, por supuesto.

Podrías seguir este ejemplo :

 #!/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() 

que produce la siguiente imagen:

contornos

Para establecer valores por encima o por debajo del rango del mapa de colores, querrá usar los métodos set_over y set_under del mapa de set_under . Si desea marcar un valor en particular, cópielo (es decir, cree una matriz enmascarada) y use el método set_bad . (Eche un vistazo a la documentación de la clase de mapa de base base: http://matplotlib.org/api/colors_api.html#matplotlib.colors.Colormap )

Parece que quieres algo como esto:

 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() 

introduzca la descripción de la imagen aquí

Las respuestas anteriores son buenas, excepto que no tienen una ubicación de marca correcta en la barra de colores. Me gusta tener las marcas en el medio del color para que el número -> mapeo de colores sea más claro. Puede resolver este problema cambiando los límites de la llamada 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) 

ejemplo de barra de colores discreta

Creo que querrías ver los colores. ListedColormap para generar tu mapa de colores , o si solo necesitas un mapa de colores estático, he estado trabajando en una aplicación que podría ayudarte.

He estado investigando estas ideas y aquí está mi valor de cinco centavos. Evita llamar a BoundaryNorm así como especificar la norm como un argumento para scatter y la colorbar . Sin embargo, no he encontrado ninguna manera de eliminar la llamada bastante larga a matplotlib.colors.LinearSegmentedColormap.from_list .

Algunos antecedentes son que matplotlib proporciona los denominados mapas formativos cualitativos, destinados a usarse con datos discretos. Set1 , por ejemplo, tiene 9 colores fácilmente distinguibles, y tab20 podría usarse para 20 colores. Con estos mapas podría ser natural usar sus primeros n colores para colorear diagtwigs de dispersión con n categorías, como lo hace el siguiente ejemplo. El ejemplo también produce una barra de colores con n colores discretos debidamente etiquetados.

 import matplotlib, numpy as np, matplotlib.pyplot as plt n = 5 from_list = matplotlib.colors.LinearSegmentedColormap.from_list cm = from_list(None, plt.cm.Set1(range(0,n)), n) x = np.arange(99) y = x % 11 z = x % n plt.scatter(x, y, c=z, cmap=cm) plt.clim(-0.5, n-0.5) cb = plt.colorbar(ticks=range(0,n), label='Group') cb.ax.tick_params(length=0) 

que produce la imagen de abajo. La n en la llamada a Set1 especifica los primeros n colores de ese mapa de colores, y la última n en la llamada a from_list especifica la construcción de un mapa con n colores (el valor predeterminado es 256). Para establecer cm como el mapa de plt.set_cmap predeterminado con plt.set_cmap , encontré que era necesario darle un nombre y registrarlo, a saber:

 cm = from_list('Set15', plt.cm.Set1(range(0,n)), n) plt.cm.register_cmap(None, cm) plt.set_cmap(cm) ... plt.scatter(x, y, c=z) 

diagrama de dispersión con colores disrete