python - Corrección de ticks matplotlib colorbar
contourf colorbar python (2)
Coloqué una barra de color junto a un mapa de coropletas. Debido a que los datos que se trazan son valores discretos en lugar de continuos, he usado un LinearSegmentedColormap (usando la receta del libro de cocina scipy ), que he inicializado con mi valor máximo contado + 1, para mostrar un color para 0. Sin embargo, ahora tengo dos problemas:
Las etiquetas de tic están incorrectamente espaciadas (excepto 5, más o menos); deben ubicarse en el medio del color que identifican; es decir, 0 - 4 debe moverse hacia arriba, y 6 - 10 debe moverse hacia abajo.
Si inicializo la barra de colores con
drawedges=True
, para que puedadrawedges=True
un estilo a sus propiedades dedividers
, obtengo esto:
Estoy creando mi mapa de color y la barra de color de esta manera:
cbmin, cbmax = min(counts), max(counts)
# this normalises the counts to a 0,1 interval
counts /= np.max(np.abs(counts), axis=0)
# density is a discrete number, so we have to use a discrete color ramp/bar
cm = cmap_discretize(plt.get_cmap(''YlGnBu''), int(cbmax) + 1)
mappable = plt.cm.ScalarMappable(cmap=cm)
mappable.set_array(counts)
# set min and max values for the colour bar ticks
mappable.set_clim(cbmin, cbmax)
pc = PatchCollection(patches, match_original=True)
# impose our colour map onto the patch collection
pc.set_facecolor(cm(counts))
ax.add_collection(pc,)
cb = plt.colorbar(mappable, drawedges=True)
Entonces me pregunto si mi conversión de los recuentos a un intervalo de 0.1 es uno de los problemas.
Actualización:
Después de haber probado lo que Hooked sugirió, el valor 0 es correcto, pero los valores posteriores se establecen progresivamente más altos, hasta el punto donde 9 es donde 10 debería ser:
Aquí está el código que utilicé:
cb = plt.colorbar(mappable)
labels = np.arange(0, int(cbmax) + 1, 1)
loc = labels + .5
cb.set_ticks(loc)
cb.set_ticklabels(labels)
Y solo para confirmar, las labels
definitivamente tienen los valores correctos:
In [3]: np.arange(0, int(cbmax) + 1, 1)
Out[3]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
Puede controlar la ubicación y las etiquetas a mano. Comenzaré con un cmap_discretize
lineal generado a partir de cmap_discretize
en la página que vinculó :
import numpy as np
import pylab as plt
# The number of divisions of the cmap we have
k = 10
# Random test data
A = np.random.random((10,10))*k
c = cmap_discretize(''jet'', k)
# First show without
plt.subplot(121)
plt.imshow(A,interpolation=''nearest'',cmap=c)
plt.colorbar()
# Now label properly
plt.subplot(122)
plt.imshow(A,interpolation=''nearest'',cmap=c)
cb = plt.colorbar()
labels = np.arange(0,k,1)
loc = labels + .5
cb.set_ticks(loc)
cb.set_ticklabels(labels)
plt.show()
Usted está sufriendo de un error "uno por uno". Tienes 10 ticklabels repartidos en 11 colores. Es posible que pueda corregir el error utilizando np.linspace
lugar de np.arange
. Usando np.linspace
el tercer argumento es el número de valores deseados. Esto reduce la cantidad de gimnasia mental necesaria para evitar el error "uno por uno":
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.cm as cm
import matplotlib.colors as mcolors
def colorbar_index(ncolors, cmap):
cmap = cmap_discretize(cmap, ncolors)
mappable = cm.ScalarMappable(cmap=cmap)
mappable.set_array([])
mappable.set_clim(-0.5, ncolors+0.5)
colorbar = plt.colorbar(mappable)
colorbar.set_ticks(np.linspace(0, ncolors, ncolors))
colorbar.set_ticklabels(range(ncolors))
def cmap_discretize(cmap, N):
"""Return a discrete colormap from the continuous colormap cmap.
cmap: colormap instance, eg. cm.jet.
N: number of colors.
Example
x = resize(arange(100), (5,100))
djet = cmap_discretize(cm.jet, 5)
imshow(x, cmap=djet)
"""
if type(cmap) == str:
cmap = plt.get_cmap(cmap)
colors_i = np.concatenate((np.linspace(0, 1., N), (0.,0.,0.,0.)))
colors_rgba = cmap(colors_i)
indices = np.linspace(0, 1., N+1)
cdict = {}
for ki,key in enumerate((''red'',''green'',''blue'')):
cdict[key] = [ (indices[i], colors_rgba[i-1,ki], colors_rgba[i,ki])
for i in xrange(N+1) ]
# Return colormap object.
return mcolors.LinearSegmentedColormap(cmap.name + "_%d"%N, cdict, 1024)
fig, ax = plt.subplots()
A = np.random.random((10,10))*10
cmap = plt.get_cmap(''YlGnBu'')
ax.imshow(A, interpolation=''nearest'', cmap=cmap)
colorbar_index(ncolors=11, cmap=cmap)
plt.show()