Correction des tiques matplotlib colorbar
j'ai placé une barre de couleur à côté d'un choropleth carte. Parce que les données tracées sont des valeurs discrètes plutôt que des valeurs continues, j'ai utilisé un colormap de linéarité (en utilisant la recette de la scipy livre de cuisine), que j'ai initialisé avec ma valeur comptée max + 1, afin d'afficher une couleur pour 0. Cependant, j'ai maintenant deux problèmes:
les étiquettes des tiques sont mal espacées (sauf pour 5, plus ou moins)) – ils doivent être placés au milieu de la couleur qu'ils identifient; c. - à - d., le 0-4 doit être déplacé vers le haut, et le 6-10 doit être déplacé vers le bas.
si j'initialise la barre de couleurs avec
drawedges=True
pour que je puisse le style de sesdividers
propriétés, j'obtiens ceci:
je crée ma palette de couleurs et de barre de couleur comme suit:
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)
alors je me demande si ma conversion des comptes à un intervalle de 0,1 est une des problème.
mise à Jour :
après avoir essayé ce que Hooked a suggéré, la valeur 0 est correcte, mais les valeurs suivantes sont placées progressivement plus haut, au point où 9 est où 10 devrait être:
Voici le code que j'ai utilisé:
cb = plt.colorbar(mappable)
labels = np.arange(0, int(cbmax) + 1, 1)
loc = labels + .5
cb.set_ticks(loc)
cb.set_ticklabels(labels)
Et juste pour confirmer, labels
a certainement les valeurs correctes:
In [3]: np.arange(0, int(cbmax) + 1, 1)
Out[3]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
2 réponses
vous souffrez d'une erreur. Vous avez 10 étiquettes réparties sur 11 couleurs. Vous pourriez être en mesure de corriger l'erreur à l'aide de np.linspace
au lieu de np.arange
. En utilisant np.linspace
le troisième argument est le nombre de valeurs souhaitée. Cela réduit la quantité de gymnastique mentale nécessaire pour éviter l'erreur d'un seul coup:
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()
Vous pouvez contrôler l'emplacement et les étiquettes à la main. Je vais commencer par un cmap linéaire généré à partir de cmap_discretize
la page que vous avez lié:
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()