2016-09-14 1 views
1

J'essaye de tracer des données dans la gamme 0-69 avec une carte de couleurs sur mesure. Voici un exemple:Matplotlib: tiques de barres de couleur mal alignées?

import matplotlib.pyplot as plt 
import numpy as np 
from matplotlib.colors import LinearSegmentedColormap 

colors = [(0.9, 0.9, 0.9), # Value = 0 
      (0.3, 0.3, 0.3), # Value = 9 
      (1.0, 0.4, 0.4), # Value = 10 
      (0.4, 0.0, 0.0), # Value = 19 
      (0.0, 0.7, 1.0), # Value = 20 
      (0.0, 0.1, 0.3), # Value = 29 
      (1.0, 1.0, 0.4), # Value = 30 
      (0.4, 0.4, 0.0), # Value = 39 
      (1.0, 0.4, 1.0), # Value = 40 
      (0.4, 0.0, 0.4), # Value = 49 
      (0.4, 1.0, 0.4), # Value = 50 
      (0.0, 0.4, 0.0), # Value = 59 
      (1.0, 0.3, 0.0), # Value = 60 
      (1.0, 0.8, 0.6)] # Value = 69 

# Create the values specified above 
max_val = 69 
values = [n for n in range(max_val + 1) if n % 10 == 0 or n % 10 == 9] 

# Create colormap, first normalise values 
values = [v/float(max_val) for v in values] 
values_and_colors = [(v, c) for v, c in zip(values, colors)] 
cmap = LinearSegmentedColormap.from_list('my_cmap', values_and_colors, 
             N=max_val + 1) 

# Create sample data in range 0-69 
data = np.round(np.random.random((20, 20)) * max_val) 

ax = plt.imshow(data, cmap=cmap, interpolation='nearest') 
cb = plt.colorbar(ticks=range(0, max_val, 10)) 
plt.show() 

enter image description here

Je suis bien perplexe pourquoi les tiques colorbar ne sont pas alignées avec les séparations distinctes entre les gradients de couleurs (pour lesquels il y a 10 couleurs chacune).

J'ai essayé de placer les intervalles de données et afficher de [0, 69] à [0, 70]:

cb.locator.axis.set_view_interval(0, 70) 
cb.locator.axis.set_data_interval(0, 70) 
cb.update_ticks() 

mais cela ne semble pas faire quoi que ce soit.

S'il vous plaît quelqu'un peut-il conseiller?

Répondre

1

La façon la plus simple pour résoudre mon problème était de mettre vmax dans la définition du mappable:

ax = plt.imshow(data, cmap=cmap, interpolation='nearest', vmax=max_val + 1) 

Il était fixé à max_val parce que la classe colorbar a l'appel mappable.autoscale_None() dans son __init__, qui se couchait vmax-data.max(), à savoir 69.

Je pense Je suis juste une victime de l'utilisation du LinearSegmentedColormap de la mauvaise façon. Je souhaite que des valeurs discrètes soient affectées à des couleurs spécifiques, mais l'affichage d'une barre de couleurs associée à LinearSegmentedColormap suppose des données continues et, par conséquent, définit par défaut des limites non spécifiées à data.min() et data.max(), c'est-à-dire dans ce cas 0 et 69.