Colormaps de Matplotlib: Personalización de tus esquemas de color

La visualización de datos es una de las mejores maneras (si no la mejor) para que los analistas de datos y los científicos de datos representen información compleja y generen insights significativos. Para aprovechar al máximo tu oportunidad de comunicarte con los interesados, he recopilado información útil sobre las paletas de colores de Matplotlib. 

Como verás en este artículo, Matplotlib es una biblioteca de visualización extremadamente versátil y extensible en Python. Ofrece todas las opciones, desde gráficos simples hasta visuales completamente interactivos. Si no estás generalmente familiarizado con Python, te animo a que te inscribas en nuestro curso de Introducción a Python antes de que comencemos para entender su fundamento. Personalmente, también tengo la Ficha de Referencia de Python a mano porque es una referencia útil para las funciones comunes.

Elegir la Paleta de Colores Correcta de Matplotlib

Una de las primeras cosas a considerar es decidir entre colormaps secuenciales, divergentes o categorizados. Otros factores importantes a considerar al elegir colormaps incluyen la uniformidad perceptual, es decir, que las diferencias iguales en los valores de los datos se perciban como diferencias iguales en el color, y el uso de opciones de colormaps amigables para daltónicos para hacer que sus visuales sean accesibles para todas las audiencias.

También debe considerar diferentes estándares de dominio al elegir colormaps. Por ejemplo, diferentes tonos de azul representan diferentes profundidades de agua en estudios oceanográficos. Si no está seguro sobre el colormap adecuado para su visualización, hay diferentes herramientas y recursos disponibles para orientarse. En particular, nuestro propio curso Introducción a la Visualización de Datos con Matplotlib le ayuda a trabajar a través de muchos escenarios.

Diferentes Colormaps en Matplotlib

En Python, el módulo matplotlib.colormaps proporciona acceso a colormaps integrados, lo que le ayuda a seleccionar el esquema más adecuado para su proyecto. A continuación se presentan las categorías más comunes de opciones:

Colormaps secuenciales

Las colormaps secuenciales representan datos ordenados que progresan desde valores bajos hacia valores altos. Realizan una transición de tonos claros a oscuros, mostrando la magnitud de los datos en diferentes niveles. Un ejemplo de una colormap secuencial se encuentra en los mapas de calor para datos de temperatura, donde los colores más claros representan temperaturas más frescas y los tonos más oscuros representan temperaturas más calientes.

Supongamos que tienes un conjunto de datos con columnas de fecha y temperatura. El siguiente código creará un mapa de calor para la temperatura.

# Importar las bibliotecas necesarias import numpy as np import pandas as pd import matplotlib.pyplot as plt import matplotlib.colors as mcolors # Paso 1: Extraer información de mes y día de la columna de fechas calendar_data = temperature_data.copy() # Crear una copia con la que trabajar calendar_data['Month'] = calendar_data['Date'].dt.strftime('%B') calendar_data['Day'] = calendar_data['Date'].dt.day # Paso 2: Definir el orden de los meses para una secuencia de calendario natural month_names = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] # Convertir la columna 'Mes' a un tipo categórico con el orden especificado calendar_data['Month'] = pd.Categorical(calendar_data['Month'], categories=month_names, ordered=True) # Paso 3: Pivotear los datos para crear una tabla estructurada para la gráfica de calor monthly_temperature_table = calendar_data.pivot(index='Month', columns='Day', values='Temperature') # Paso 4: Configurar el gráfico para la gráfica de calor plt.figure(figsize=(12, 8)) # Definir una normalización personalizada para el rango de temperaturas (opcional) norm = mcolors.Normalize(vmin=15, vmax=35) # Crear la gráfica de calor con una mapa de colores secuenciales heatmap = plt.imshow(monthly_temperature_table, cmap='YlOrRd', aspect='auto', norm=norm) # Añadir una barra de colores para representar la temperatura colorbar = plt.colorbar(heatmap, orientation='horizontal') colorbar.set_label('Temperature (°C)', labelpad=10) # Etiquetar los ejes plt.xlabel('Day of the Month') plt.ylabel('Month') # Establecer las marcas en el eje y para mostrar los nombres de los meses en lugar de números plt.yticks(ticks=np.arange(len(month_names)), labels=month_names) # Añadir un título a la gráfica de calor plt.title('Monthly Temperature Heatmap (Sequential Colormap)') # Mostrar el gráfico plt.grid(False) plt.show()

Ejemplo de visualización de mapas de colores secuenciales de Matplotlib. Imagen del autor

Mapas de colores divergentes

Las escalas de colores divergentes resaltan datos con desviaciones de un valor central en ambas direcciones. Las escalas de colores divergentes tienen colores contrastantes para las direcciones positiva y negativa. Una aplicación común de las escalas de colores divergentes es en datos financieros para representar ganancias y pérdidas.

# Establecer 'Mes' como índice profit_loss_df.set_index('Month', inplace=True) # Establecer el tamaño de la figura plt.figure(figsize=(8, 4)) # Crear una escala de colores divergente cmap = plt.cm.RdYlGn # Mostrar los datos como un mapa de calor usando imshow im = plt.imshow(profit_loss_df.T, cmap=cmap, aspect='auto', vmin=-np.max(np.abs(profit_loss_data)), vmax=np.max(np.abs(profit_loss_data))) # Añadir una barra de colores con etiqueta cbar = plt.colorbar(im) cbar.set_label('Profit/Loss ($)') # Añadir anotaciones a cada celda for i, month in enumerate(profit_loss_df.index): plt.text(i, 0, f'{profit_loss_df.loc[month, "Profit/Loss"]:.2f}', ha='center', va='center', color='black') # Establecer etiquetas y marcas para los ejes x e y plt.xlabel('Month') plt.ylabel('') # No se necesita etiqueta para el eje y plt.xticks(ticks=range(len(profit_loss_df.index)), labels=profit_loss_df.index, rotation=45) plt.yticks([]) # Ocultar las marcas del eje y, ya que solo tenemos una fila # Añadir título plt.title('Profit/Loss Heatmap (Diverging Colormap)') # Ajustar el diseño para una mejor visualización plt.tight_layout() # Mostrar gráfico plt.show()

Ejemplo de visualización de escala de colores divergente con Matplotlib. Imagen del autor.

Mapas de color cíclicos

Los mapas de color cíclicos son útiles para visualizar datos que representan un patrón repetitivo o cíclico, como ángulos, fases de ondas o hora del día. Un ejemplo de uso de un mapa de color cíclico es la visualización de las fases de una función periódica, como una onda senoidal.

# Crear datos para una onda senoidal x = np.linspace(0, 2 * np.pi, 100) # Valores X de 0 a 2π (un ciclo completo) y = np.sin(x) # Valores Y (seno de X) # Crear una figura y un eje plt.figure(figsize=(10, 6)) # Crear un gráfico de dispersión con un mapa de color cíclico # Colorear los puntos según su posición en el ciclo de la onda senoidal points = plt.scatter(x, y, c=x, cmap='twilight', edgecolor='black') # Añadir una barra de color para mostrar la fase de la onda cbar = plt.colorbar(points) cbar.set_label('Wave Phase (Radians)', rotation=270, labelpad=15) # Etiquetar los ejes plt.xlabel('Angle (Radians)') plt.ylabel('Sine Value') # Añadir un título plt.title('Sine Wave with Cyclic Colormap (Twilight)') # Mostrar el gráfico plt.grid(True) plt.show()

Ejemplo de visualización de mapa de color cíclico en Matplotlib. Imagen del autor.

Mapas de color cualitativos

Las colormaps cualitativas son ideales para representar datos categorizados sin un orden particular de las categorías. Un caso de uso común de las colormaps cualitativas es un gráfico de torta donde cada segmento representa una categoría diferente que puede ser fácilmente distinguible.

# Datos categorizados de ejemplo categories = ['Category A', 'Category B', 'Category C', 'Category D', 'Category E'] values = [20, 35, 25, 10, 10] # Establecer el tamaño de la figura plt.figure(figsize=(8, 8)) # Definir una colormap cualitativa manualmente colors = ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3'] # Códigos hexadecimales de color seleccionados manualmente # Crear un gráfico de torta plt.pie(values, labels=categories, autopct='%1.1f%%', startangle=90, colors=colors) # Una relación de aspectos igual asegura que la torta se dibuje como un círculo plt.axis('equal') # Agregar un título plt.title('Pie Chart with Qualitative Colormap') # Mostrar el gráfico plt.show()

Ejemplo de visualización de colormap cualitativa de Matplotlib. Imagen del Autor.

Colormaps arcoíris

Las colormaps arcoíris como hsv se utilizan cuando se necesita un amplio rango de tonos.

# Generar datos cíclicos x = np.linspace(0, 2 * np.pi, 500) y = np.sin(x) # Crear una gráfica con mapa de colores arcoíris plt.scatter(x, y, c=x, cmap='hsv', s=50) # Añadir una barra de colores plt.colorbar(label='Phase') # Añadir etiquetas y título plt.xlabel('Angle (radians)') plt.ylabel('Sine Value') plt.title('Cyclic Data Visualization using HSV Colormap') # Mostrar la gráfica plt.show()

Ejemplo de visualización de mapa de colores arcoíris con Matplotlib. Imagen del autor.

Mapas de colores uniformes en percepción

Mapas de colores como inferno y plasma ofrecen mejor visibilidad a través de diferentes medios de visualización.

# Generar datos sintéticos de elevación x = np.linspace(-5, 5, 100) y = np.linspace(-5, 5, 100) X, Y = np.meshgrid(x, y) Z = np.sin(np.sqrt(X**2 + Y**2)) * 100 # Datos de elevación # Trazar los datos de elevación utilizando el mapa de colores 'plasma' plt.contourf(X, Y, Z, cmap='plasma') # Añadir una barra de colores plt.colorbar(label='Elevation (m)') # Añadir título y etiquetas plt.title('Topographic Map (Plasma Colormap)') plt.xlabel('X Coordinate') plt.ylabel('Y Coordinate') # Mostrar la gráfica plt.show()

Ejemplo de visualización de mapa de colores uniforme perceptual de Matplotlib. Imagen del Autor.

Creación y Modificación de Mapas de Colores de Matplotlib

Aunque Matplotlib tiene una amplia variedad de mapas de colores integrados, hay situaciones en las que desea personalizar sus colores. Las herramientas clave para crear mapas de colores personalizados en Matplotlib son ListedColormap y LinearSegmentedColormap.

Creación de un mapa de colores personalizado con ListedColormap

ListedColormap le permite crear un mapa de colores a partir de una lista de colores específicos. Este método es útil al asignar colores específicos a categorías distintas en datos categorizados. 

from matplotlib.colors import ListedColormap # Datos categorizados categories = ['Category A', 'Category B', 'Category C', 'Category D'] values = [25, 40, 35, 30] # Lista de colores personalizados para el mapa de colores (por ejemplo, tonos de azul, verde, rojo y púrpura) custom_colors = ['#1f77b4', '#2ca02c', '#d62728', '#9467bd'] # Crear un ListedColormap utilizando los colores personalizados custom_cmap = ListedColormap(custom_colors) # Establecer el tamaño de la figura plt.figure(figsize=(8, 6)) # Crear un gráfico de barras con el mapa de colores personalizado bars = plt.bar(categories, values, color=custom_cmap.colors) # Añadir un título plt.title('Bar Chart with Custom ListedColormap') # Etiquetar los ejes plt.xlabel('Categories') plt.ylabel('Values') # Mostrar la gráfica plt.show()

Matplotlib mapa de colores personalizado con ListedColormap. Imagen del autor.

Crear un mapa de colores personalizado con LinearSegmentedColormap

LinearSegmentedColormap permite crear mapas de colores que transicionan suavemente entre colores. Esto es útil porque los datos continuos a menudo requieren cambios de color en gradiente. Aquí, también estoy especificando el número de intervalos que quiero para mi visualización.

from matplotlib.colors import LinearSegmentedColormap # Crear una cuadrícula de valores para una función Gaussiana 2D x = np.linspace(-2, 2, 500) y = np.linspace(-2, 2, 500) X, Y = np.meshgrid(x, y) Z = np.exp(- (X**2 + Y**2)) # Definir un mapa de colores personalizado que_transita de azul a blanco a rojo colors = ['blue', 'white', 'red'] custom_cmap = LinearSegmentedColormap.from_list('blue_white_red', colors) # Ajustar el número de clases de color (niveles discretos) # Especificar el número de niveles (por ejemplo, 10 para 10 bandas de color distintivas) num_classes = 10 levels = np.linspace(Z.min(), Z.max(), num_classes) # Establecer el tamaño de la figura plt.figure(figsize=(8, 6)) # Graficar la función Gaussiana 2D con el mapa de colores ajustado contour = plt.contourf(X, Y, Z, levels=levels, cmap=custom_cmap) # Añadir una barra de colores para mostrar las clases de color discretas plt.colorbar(contour, label='Gaussian Function Value') # Añadir etiquetas para los ejes plt.xlabel('X') plt.ylabel('Y') # Añadir un título plt.title(f'2D Gaussian with {num_classes} Discrete Color Classes') # Mostrar la gráfica plt.show()

Matplotlib personalizando el ajuste del número de clases de color. Imagen del autor.

Personalizando rangos de color e intensidad

<Puedes controlar la intensidad o el rango de colores en una cola de colores existente manipulando su normalización o cortándola para usar un subconjunto de los colores disponibles. En el siguiente ejemplo, los rangos de colores se cortan para mostrar temperaturas entre 16 y 40 grados Celsius.

# Configurar el gráfico para la mapa de calor plt.figure(figsize=(12, 8)) # Definir una normalización personalizada para el rango de temperatura norm = mcolors.Normalize(vmin=16, vmax=40) # Crear la mapa de calor con una cola de colores secuencial heatmap = plt.imshow(monthly_temperature_table, cmap='YlOrRd', aspect='auto', norm=norm) # Añadir la barra de colores para representar la temperatura colorbar = plt.colorbar(heatmap, orientation='horizontal') colorbar.set_label('Temperature (°C)', labelpad=10) # Etiquetar los ejes plt.xlabel('Day of the Month') plt.ylabel('Month') # Establecer las marcas en el eje y para mostrar nombres de meses en lugar de números plt.yticks(ticks=np.arange(len(month_names)), labels=month_names) # Añadir un título a la mapa de calor plt.title('Monthly Temperature Heatmap (Sequential Colormap)') # Mostrar el gráfico plt.grid(False) plt.show()

Matplotlib personalizando rangos de colores e intensidad. Imagen del autor.

Combinando colas de colores existentes

También puedes combinar colormaps existentes mezclando varios colormaps para crear visualizaciones más complejas.

from matplotlib.colors import LinearSegmentedColormap, Normalize # Crear datos sintéticos de elevación x = np.linspace(-180, 180, 500) # Longitud y = np.linspace(-90, 90, 250) # Latitud X, Y = np.meshgrid(x, y) Z = 5000 * np.sin(np.sqrt(X**2 + Y**2) * np.pi / 180) # Datos sintéticos de elevación # Definir los colormaps base ('viridis' y 'cividis') cmap1 = plt.get_cmap('viridis') cmap2 = plt.get_cmap('cividis') # Crear un colormap personalizado mezclando los dos colormaps base def blend_colormaps(cmap1, cmap2, blend_ratio=0.5): """Blend two colormaps together.""" c1 = cmap1(np.linspace(0, 1, 256)) c2 = cmap2(np.linspace(0, 1, 256)) blended_colors = (1 - blend_ratio) * c1 + blend_ratio * c2 return LinearSegmentedColormap.from_list('blended_cmap', blended_colors) # Crear el colormap mezclado custom_cmap = blend_colormaps(cmap1, cmap2, blend_ratio=0.5) # Normalizar los datos para la visualización norm = Normalize(vmin=-5000, vmax=5000) # Establecer el tamaño del gráfico plt.figure(figsize=(12, 6)) # Representar los datos sintéticos de elevación con el colormap mezclado contour = plt.contourf(X, Y, Z, levels=100, cmap=custom_cmap, norm=norm) # Añadir una barra de colores para mostrar el mapeo de color mezclado plt.colorbar(contour, label='Elevation (meters)') # Añadir etiquetas para los ejes plt.xlabel('Longitude') plt.ylabel('Latitude') # Añadir un título plt.title('Geographical Elevation Data with Blended Colormap (Viridis + Cividis)') # Mostrar el gráfico plt.show()

Matplotlib Combinando colormaps existentes. Imagen del autor.

Invertiendo colormaps utilizando el sufijo _r

Puedes invertir cualquier colormap en Matplotlib adicionando el sufijo _r a su nombre.

# Configurar el gráfico para la mapa de calor plt.figure(figsize=(12, 8)) # Crear una normalización personalizada para el rango de colores norm = mcolors.Normalize(vmin=16, vmax=40) # Trazar el mapa de calor utilizando imshow con el colormap secuencial im = plt.imshow(monthly_temperature_table, cmap='YlOrRd_r', norm=norm, aspect='equal') # Añadir una barra de colores con una orientación horizontal cbar = plt.colorbar(im, orientation='horizontal', pad=0.1) cbar.set_label('Temperature (°C)', labelpad=10) # Añadir etiquetas para los ejes plt.xlabel('Day of the Month') plt.ylabel('Month') # Establecer las marcas en el eje y para mostrar nombres de meses en lugar de números plt.yticks(ticks=np.arange(len(month_names)), labels=month_names) # Añadir un título plt.title('Temperature Heatmap (Sequential Colormap)') # Mostrar el gráfico plt.show()

Matplotlib Invertiendo colormaps utilizando el sufijo _r. Imagen del autor.

Manejo de Errores Comunes en los Colormaps de Matplotlib

Al trabajar con mapas de colores en Matplotlib, es posible que encuentres errores que afecten tu flujo de trabajo. A continuación se presentan algunos de estos errores y cómo solucionarlos.

AttributeError: el módulo ‘matplotlib’ no tiene el atributo ‘colormaps’

Este error ocurre cuando usas versiones de Matplotlib anteriores a la 3.4.0 para acceder a matplotlib.colormaps. El atributo colormaps fue introducido en Matplotlib 3.4.0. Primero, verifica tu versión de Matplotlib utilizando el código a continuación para solucionar este error.

import matplotlib print(matplotlib.__version__)

Actualiza utilizando el siguiente comando de pip.

pip install --upgrade matplotlib

Si tienes problemas al actualizar tu versión de Matplotlib, intenta el siguiente método para acceder a los mapas de colores.

plt.get_cmap('viridis') # en lugar de matplotlib.colormaps['viridis']

Asignaciones de color incorrectas

Puede experimentar asignaciones de color incorrectas cuando pasa un valor fuera del rango esperado o cuando la cola de colores se aplica incorrectamente. La asignación de color incorrecta también puede surgir si la cola de colores está destinada a datos continuos pero se aplica a datos categorizados o viceversa.

Para asegurarse de que sus datos estén dentro del rango esperado, siempre normalice o escalelos utilizando los parámetros vmax y vmin.

import matplotlib.colors as mcolors # Crear un conjunto de datos de muestra de temperatura data = np.random.rand(10, 10) * 100 # Ajustar el rango para que coincida con sus datos # Crear una instancia de normalización de color para escalar los datos al rango de la cola de colores norm = mcolors.Normalize(vmin=0, vmax=100) # Crear una gráfica de calor utilizando la cola de colores 'viridis' y la normalización especificada plt.imshow(data, cmap='viridis', norm=norm, interpolation='nearest') plt.colorbar() plt.show()

Para un control más fino, puede definir explícitamente los límites de color utilizando los parámetros boundaries o norm en las funciones de trazado.

Artifacts visuales y resultados inesperados

Al trabajar con datos discretos o de baja resolución, puede experimentar bandas de color no deseadas, exceso de contraste o sangrado de color. El problema ocurre cuando sus datos tienen un rango limitado pero se muestra con una paleta de colores continua.

Para resolver este problema, utilice más puntos de datos o ajuste el número de niveles de color para suavizar las transiciones.

# Aumente el número de bins en la paleta de colores cmap = plt.get_cmap('viridis', 256) plt.imshow(data, cmap=cmap)

Puede dividir la paleta de colores en niveles fijos para manejar datos discretos donde sea apropiado.

cmap = plt.get_cmap('inferno', 10) # Dividir la paleta de colores en 10 niveles discretos plt.imshow(data, cmap=cmap)

También puede verificar la configuración de visualización y ajustar la resolución, especialmente al guardar las visualizaciones, para evitar gráficos de baja resolución

plt.savefig('plot.png', dpi=300) # Guarde la figura con una mayor resolución

Distorsión del color debido al recorte

La distorsión de color ocurre cuando los datos contienen valores extremos fuera del rango de color esperado. Esto provoca que partes de los datos se recorten y se asignen el color mínimo o máximo en la paleta de colores.

Para evitar la distorsión de color, ajuste los límites de color utilizando vmin y vmax para que coincida con el rango de sus datos, evitando el recorte.

plt.imshow(data, cmap='plasma', vmin=0, vmax=100)

Además, debe utilizar una escala robusta para manejar los valores atípicos estableciendo límites personalizados que excluyan los valores extremos.

import numpy as np robust_vmin, robust_vmax = np.percentile(data, [2, 98]) # Utilice percentiles para eliminar valores atípicos extremos plt.imshow(data, cmap='inferno', vmin=robust_vmin, vmax=robust_vmax)

La paleta de colores no se muestra correctamente en gráficos 3D

Si hay un problema con cómo se mapean los datos en la superficie 3D, las paletas de colores pueden no mostrarse correctamente en las visualizaciones 3D. Para resolverlo, asegúrese de que los datos del eje z estén normalizados para ajustarse dentro del rango esperado de la paleta de colores. También utilice los límites adecuados de la paleta de colores para capturar todo el rango de los valores z.

from mpl_toolkits.mplot3d import Axes3D Generar datos de muestra para una trama de superficie 3D X, Y = np.meshgrid(np.linspace(-5, 5, 50), np.linspace(-5, 5, 50)) Z = np.sin(np.sqrt(X**2 + Y**2)) Crear un objeto de ejes 3D ax = plt.axes(projection='3d') Trazar la superficie utilizando la paleta de colores 'viridis' y ajustando los límites de color ax.plot_surface(X, Y, Z, cmap='viridis', vmin=np.min(Z), vmax=np.max(Z)) plt.show()

Conclusión

Elegir la paleta de colores adecuada es un paso importante porque realmente afecta cómo los usuarios ven y comprenden sus datos. En mi opinión, dedicar mucho tiempo al análisis de datos y ser descuidado en la última etapa, que es la parte donde comunicas tus hallazgos, es un gran error.

Afortunadamente, Matplotlib ofrece muchas opciones para asegurarse de que tus visuales narren una historia convincente. Inscríbete en nuestro curso, Introducción a la Visualización de Datos con Matplotlib, para convertirte en un experto. Además, si eres usuario de Python y también utilizas Seaborn para la visualización (es genial saber ambos), lee nuestra Guía Rápida para Elegir Colores en Seaborn y luego sigue con nuestro Introducción a la Visualización de Datos con Seaborn curso.

Source:
https://www.datacamp.com/tutorial/matplotlib-colormaps