Matplotlib ofrece también las funciones equivalentes matplotlib.pyplot.pcolormesh y matplotlib.pyplot.pcolor, aunque en la documentación de la librería se recomienda usar la primera, así que nos centramos en ella: en teoría "crea una gráfica en pseudo-colores con un grid no rectangular". Comencemos por su sintaxis:
pcolormesh([x, y,] c, **kwargs)
...donde c es un array 2D de escalares, valores que serán "mapeados" a un conjunto de colores determinado por el parámetro cmap, y x e y, parámetros opcionales, definen las coordenadas de las esquinas de los rectángulos que se mostrarán del color correspondiente. En resumen, dos claras diferencias con respecto a la función plt.imshow: los datos deben encontrarse en un array de 2 dimensiones (lo que solo ocurre con las imágenes en blanco y negro, cualquier otra no podría mostrarse usando esta función) y los "puntos" de la imagen mostrada no son puntos en realidad, sino rectángulos de tamaños a determinar por los parámetros x e y.
De hecho, los "rectángulos" en cuestión están limitados por los valores de x e y. Es decir, si en x tenemos, pongamos por caso, los valores 1, 3, y 5, estos tres valores definen dos rectángulos, uno que va a tener como límites en una dimensión los valores 1 y 3, y otro que va a tener como límites los valores 3 y 5.
Veamos esta función en la práctica: Creamos las estructuras x e y (simples listas en este ejemplo), y un array conteniendo los datos a mostrar:
x = [1, 3, 4]
y = [2, 3, 6]
z = np.linspace(0, 255, 9).reshape(3, 3)
z
plt.pcolormesh(x, y, z, cmap = "gray");
Comprobamos que la lista x se representa horizontalmente (de izquierda a derecha), y la lista y, verticalmente (de abajo arriba), como en cualquier gráfica 2D de las que hemos visto. Comprobamos también que, efectivamente, los valores de x y de y determinan los límites de los rectángulos, lo que significa que el array z no necesita tener más que x-1 elementos horizontales e y-1 elementos verticales. O dicho con otras palabras, de nuestro array z de tamaño 3x3 se está ignorando una fila y una columna.
Según la documentación, la celda c[i, j] viene limitada en su esquina inferior izquierda por (x[i, j], y[i, j]) y, en su esquina superior derecha por (x[i + 1, j + 1], y[i + 1, j + 1]). Para ver claramente los datos que se utilizan y cómo se disponen en el gráfico, repitamos la anterior gráfica con un mapa de color con una paleta discreta y añadamos un barra de colores:
plt.pcolormesh(x, y, z, cmap = "Paired");
plt.colorbar();
Comprobamos -no demasiado sorprendentemente- que los datos mostrados son los del bloque superior izquierdo. Es decir, se ignora -en este caso- la última fila y la última columna.
Otro factor relevante es el orden en el que se muestran los datos, correspondiendo la primera fila del array a la fila inferior del gráfico y mostrándose los datos horizontalmente en el mismo orden que en el array. Esto significa que si partimos de un array plano:
a = z[:2, :2].flatten()
a
...los datos se van a mostrar, una vez redimensionados, de izquierda a derecha y de abajo hacia arriba:
plt.pcolormesh(a.reshape(2, 2), cmap = "Paired");
plt.colorbar();
¿Y qué implicaciones tiene esto si se utiliza como array de entrada una imagen? En primer lugar, pcolormesh solo acepta arrays bidimensionales. La imagen vista en el apartado anterior tenía cuatro capas:
img = plt.imread("https://www.interactivechaos.com/sites/default/files/data/sunset.png")
img.shape
Mostremos entonces una de ellas con pcolormesh:
plt.pcolormesh(img[:, :, 0]);
Horizontalmente no hay diferencias, pero la imagen se muestra invertida.