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:

enter image description here

  1. 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.

  2. si j'initialise la barre de couleurs avec drawedges=True pour que je puisse le style de ses dividers propriétés, j'obtiens ceci:

enter image description here

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:

enter image description here

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])
17
demandé sur urschrei 2013-09-09 22:11:04

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

enter image description here

17
répondu unutbu 2013-09-09 21:54:38

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

enter image description here

8
répondu Hooked 2013-09-09 19:25:10