Matplotlib: ListedColormapap no mapea colores

Estoy teniendo problemas para entender por qué un cmap personalizado no se está plt.imshow correctamente a una imagen usando plt.imshow .

Cuando resr matriz 2-D sin especificar un cmap, veo:

 resr = np.array([[0,2],[3,4]],dtype=int) plt.imshow(resr) 

introduzca la descripción de la imagen aquí

Esto se ve bien. Cuando bash pasar un cmap de mis colores especificados usando:

 cmap1 = ['#7fc97f', '#ffff99', '#386cb0', '#f0027f'] cmap = colors.ListedColormap(cmap1) plt.imshow(resr, cmap=cmap) 

Veo:

introduzca la descripción de la imagen aquí

Por alguna razón, el color cmap1[3] se asigna a los valores resr 3 y 4 . ¿Por qué está pasando esto?

Veo dos opciones aquí:

A. Mapear datos a categorías

 import matplotlib.pyplot as plt import numpy as np import matplotlib.colors as colors from mpl_toolkits.axes_grid1 import make_axes_locatable resr = np.array([[0,2],[3,4]],dtype=int) u, ind = np.unique(resr, return_inverse=True) norm = colors.BoundaryNorm(np.arange(len(u)+1)-.5, len(u)) cmap1 = ['#7fc97f', '#ffff99', '#386cb0', '#f0027f'] cmap = colors.ListedColormap(cmap1) fig,ax = plt.subplots() im = ax.imshow(ind.reshape(resr.shape), cmap=cmap,norm=norm) divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="5%") cb = plt.colorbar(im, cmap=cmap,norm=norm,cax=cax) cb.set_ticks(np.arange(len(u))) cb.ax.set_yticklabels(cmap1) cb.ax.tick_params(labelsize=10) plt.show() 

B. Mapa de categorías a los datos

 import matplotlib.pyplot as plt import numpy as np import matplotlib.colors as colors from mpl_toolkits.axes_grid1 import make_axes_locatable resr = np.array([[0,2],[3,4]],dtype=int) u = np.unique(resr) bounds = np.concatenate(([resr.min()-1], u[:-1]+np.diff(u)/2. ,[resr.max()+1])) print(bounds) norm = colors.BoundaryNorm(bounds, len(bounds)-1) cmap1 = ['#7fc97f', '#ffff99', '#386cb0', '#f0027f'] cmap = colors.ListedColormap(cmap1) fig,ax = plt.subplots() im = ax.imshow(resr, cmap=cmap,norm=norm) divider = make_axes_locatable(ax) cax = divider.append_axes("right", size="5%") cb = plt.colorbar(im, cmap=cmap,norm=norm,cax=cax) cb.set_ticks(bounds[:-1]+np.diff(bounds)/2.) cb.ax.set_yticklabels(cmap1) cb.ax.tick_params(labelsize=10) plt.show() 

El resultado es el mismo para ambos casos.

introduzca la descripción de la imagen aquí

Siguiendo el comentario de @ ImportanceOfBeingErnest que proporciona un enlace a su publicación , pude encontrar una solución.

El truco consistía en utilizar pass np.unique(resr) a BoundaryNorm . Algo como:

 resr = np.array([[0,2],[3,4]],dtype=int) norm = colors.BoundaryNorm(np.unique(resr), len(np.unique(resr))-1) cmap1 = ['#7fc97f', '#ffff99', '#386cb0', '#f0027f'] cmap = colors.ListedColormap(cmap1) plt.imshow(resr, cmap=cmap,norm=norm);plt.colorbar() 

Lo que devuelve el resultado esperado:

introduzca la descripción de la imagen aquí