web-dev-qa-db-fra.com

Correction des tiques de la barre de couleurs matplotlib

J'ai placé une barre de couleur à côté d'une carte choroplèthe. Parce que les données tracées sont des valeurs discrètes plutôt que continues, j'ai utilisé un LinearSegmentedColormap (en utilisant la recette du livre de recettes scipy ), que j'ai initialisé avec ma valeur maximale comptée + 1, dans l'ordre pour 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) - elles doivent être situées au milieu de la couleur qu'elles identifient; c'est-à-dire que 0 - 4 doit être déplacé vers le haut, et 6 - 10 doit être déplacé vers le bas.

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

enter image description here

Je crée ma palette de couleurs et ma barre de couleurs 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)

Je me demande donc si ma conversion des comptes à un intervalle de 0,1 est l'un des problèmes.

Mettre à jour :

Après avoir essayé ce que Hooked a suggéré, la valeur 0 est correcte, mais les valeurs suivantes sont progressivement augmentées, 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 définitivement les bonnes valeurs:

In [3]: np.arange(0, int(cbmax) + 1, 1)
Out[3]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
20
urschrei

Vous souffrez d'une erreur ponctuelle. Vous avez 10 ticklabels répartis sur 11 couleurs. Vous pourrez peut-être corriger l'erreur en utilisant np.linspace au lieu de np.arange. En utilisant np.linspace le troisième argument est le nombre de valeurs souhaitées. Cela réduit la quantité de gymnastique mentale nécessaire pour éviter l'erreur de coup par 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

18
unutbu

Vous pouvez contrôler le placement et les étiquettes à la main. Je vais commencer par une cmap linéaire générée à partir de cmap_discretize le la page que vous avez liée :

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

11
Hooked