Mapas de Cores Matplotlib: Personalizando Suas Paletas de Cores

A visualização de dados é uma das melhores maneiras (se não a melhor) para analistas de dados e cientistas de dados representarem informações complexas e gerarem insights significativos. Para aproveitar ao máximo sua oportunidade de se comunicar com os interessados, compilei informações úteis sobre mapas de cores do Matplotlib. 

Como você verá neste artigo, o Matplotlib é uma biblioteca extremamente versátil e extensível de visualização em Python. Ele oferece todas as opções, desde gráficos simples até visuais completamente interativos. Se você não está geralmente familiarizado com Python, recomendo que você se inscreva em nosso curso Introdução ao Python antes de começarmos para entender sua fundação. Pessoalmente, também mantenho o Cheat Sheet do Python à mão, pois é uma referência útil para funções comuns.

Escolhendo o Mapa de Cores Certo do Matplotlib

Uma das primeiras coisas a considerar é decidir entre escalas de cores sequenciais, divergentes ou categóricas. Outros fatores importantes a considerar ao escolher escalas de cores incluem a uniformidade perceptiva, ou seja, que diferenças iguais nos valores dos dados sejam percebidas como diferenças iguais na cor, e usar opções de escalas de cores amigáveis para daltônicos para tornar seus visuais acessíveis a todos os públicos.

Você também deve considerar diferentes padrões de domínio ao escolher escalas de cores. Por exemplo, diferentes tons de azul representam diferentes profundidades de água em estudos oceanográficos. Se você estiver em dúvida sobre a escala de cores certa para sua visualização, diferentes ferramentas e recursos estão disponíveis para orientação. Em particular, nosso próprio curso Introdução à Visualização de Dados com Matplotlib ajuda você a trabalhar através de muitos cenários.

/settingsdialog
Diferentes Escalas de Cores no Matplotlib

No Python, o módulo matplotlib.colormaps fornece acesso às escalas de cores embutidas, o que ajuda você a selecionar o esquema mais adequado para seu projeto. A seguir estão as categorias mais comuns de opções:

Escalas de cores sequenciais

As colormaps sequenciais representam dados ordenados que progressem de valores baixos para altos. Elas transitam de tons claros para escuros, mostrando a magnitude dos dados em diferentes níveis. Um exemplo de uma colormap sequencial é em mapas de calor para dados de temperatura, onde cores mais claras representam temperaturas mais frias e tons mais escuros representam temperaturas mais quentes.

Suponha que você tenha um conjunto de dados com colunas de data e temperatura. O código a seguir criará um mapa de calor para a temperatura.

# Importar bibliotecas necessárias import numpy as np import pandas as pd import matplotlib.pyplot as plt import matplotlib.colors as mcolors # Passo 1: Extrair informações de mês e dia da coluna de data calendar_data = temperature_data.copy() # Criar uma cópia para trabalhar calendar_data['Month'] = calendar_data['Date'].dt.strftime('%B') calendar_data['Day'] = calendar_data['Date'].dt.day # Passo 2: Definir a ordem dos meses para uma sequência de calendário natural month_names = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] # Converter a coluna 'Month' para um tipo categórico com a ordem especificada calendar_data['Month'] = pd.Categorical(calendar_data['Month'], categories=month_names, ordered=True) # Passo 3: Pivotar os dados para criar uma tabela estruturada para o mapa de calor monthly_temperature_table = calendar_data.pivot(index='Month', columns='Day', values='Temperature') # Passo 4: Configurar o gráfico para o mapa de calor plt.figure(figsize=(12, 8)) # Definir uma normalização personalizada para o intervalo de temperatura (opcional) norm = mcolors.Normalize(vmin=15, vmax=35) # Criar o mapa de calor com uma colormap sequencial heatmap = plt.imshow(monthly_temperature_table, cmap='YlOrRd', aspect='auto', norm=norm) # Adicionar uma barra de cores para representar a temperatura colorbar = plt.colorbar(heatmap, orientation='horizontal') colorbar.set_label('Temperature (°C)', labelpad=10) # Nomear os eixos plt.xlabel('Day of the Month') plt.ylabel('Month') # Definir os ticks do eixo y para exibir nomes de meses em vez de números plt.yticks(ticks=np.arange(len(month_names)), labels=month_names) # Adicionar um título ao mapa de calor plt.title('Monthly Temperature Heatmap (Sequential Colormap)') # Exibir o gráfico plt.grid(False) plt.show()

Exemplo de visualização de colormaps sequenciais do Matplotlib. Imagem pelo Autor

Colormaps divergentes

Mapas de cores divergentes destacam dados com desvios de um valor central em ambas as direções. Os mapas de cores divergentes têm cores contrastantes para as direções positiva e negativa. Uma aplicação comum dos mapas de cores divergentes é em dados financeiros para representar lucro e perda.

# Definir 'Mês' como índice profit_loss_df.set_index('Month', inplace=True) # Definir o tamanho da figura plt.figure(figsize=(8, 4)) # Criar um mapa de cores divergente cmap = plt.cm.RdYlGn # Exibir os dados como um 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))) # Adicionar uma barra de cores com rótulo cbar = plt.colorbar(im) cbar.set_label('Profit/Loss ($)') # Adicionar anotações em cada célula 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') # Definir rótulos e ticks dos eixos x e y plt.xlabel('Month') plt.ylabel('') # Não é necessário rótulo para o eixo y plt.xticks(ticks=range(len(profit_loss_df.index)), labels=profit_loss_df.index, rotation=45) plt.yticks([]) # Ocultar os ticks do eixo y, pois temos apenas uma linha # Adicionar título plt.title('Profit/Loss Heatmap (Diverging Colormap)') # Ajustar o layout para melhor exibição plt.tight_layout() # Mostrar o gráfico plt.show()

Exemplo de visualização de mapa de cores divergente do Matplotlib. Imagem pelo Autor.

Mapas de cores cíclicos

Mapas de cores cíclicos são úteis para visualizar dados que representam um padrão repetitivo ou cíclico, como ângulos, fases de onda ou hora do dia. Um exemplo de um mapa de cores cíclico em ação é a visualização das fases de uma função periódica, como uma onda senoidal.

# Criar dados para uma onda senoidal x = np.linspace(0, 2 * np.pi, 100) # Valores X de 0 a 2π (um ciclo completo) y = np.sin(x) # Valores Y (seno de X) # Criar um gráfico e eixo plt.figure(figsize=(10, 6)) # Criar um gráfico de dispersão com um mapa de cores cíclico # Colorir pontos pela sua posição no ciclo da onda senoidal points = plt.scatter(x, y, c=x, cmap='twilight', edgecolor='black') # Adicionar uma barra de cores para mostrar a fase da onda cbar = plt.colorbar(points) cbar.set_label('Wave Phase (Radians)', rotation=270, labelpad=15) # Rotular os eixos plt.xlabel('Angle (Radians)') plt.ylabel('Sine Value') # Adicionar um título plt.title('Sine Wave with Cyclic Colormap (Twilight)') # Exibir o gráfico plt.grid(True) plt.show()

Exemplo de visualização de mapa de cores cíclico com Matplotlib. Imagem do Autor.

Mapas de cores qualitativos

Colormap qualitativas são ideais para representar dados categóricos sem uma ordem particular das categorias. Um caso de uso comum de colormaps qualitativas é um gráfico de pizza onde cada segmento representa uma categoria diferente que pode ser facilmente distinguida.

# Exemplo de dados categóricos categories = ['Category A', 'Category B', 'Category C', 'Category D', 'Category E'] values = [20, 35, 25, 10, 10] # Definir o tamanho do gráfico plt.figure(figsize=(8, 8)) # Definir um colormap qualitativo manualmente colors = ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3'] # Códigos hexadecimais de cores selecionadas manualmente # Criar um gráfico de pizza plt.pie(values, labels=categories, autopct='%1.1f%%', startangle=90, colors=colors) # Proporção equal garante que o pizza seja desenhado como um círculo plt.axis('equal') # Adicionar um título plt.title('Pie Chart with Qualitative Colormap') # Exibir o gráfico plt.show()

Exemplo de visualização de colormap qualitativo do Matplotlib. Imagem do Autor.

Colormaps Arco-Íris

Colormaps arco-íris como hsv são usadas quando é necessário uma ampla gama de tons.

# Gerar dados cíclicos x = np.linspace(0, 2 * np.pi, 500) y = np.sin(x) # Criar um gráfico com colormap arco-íris plt.scatter(x, y, c=x, cmap='hsv', s=50) # Adicionar uma barra de cores plt.colorbar(label='Phase') # Adicionar rótulos e título plt.xlabel('Angle (radians)') plt.ylabel('Sine Value') plt.title('Cyclic Data Visualization using HSV Colormap') # Exibir o gráfico plt.show()

Exemplo de visualização de colormap arco-íris com Matplotlib. Imagem pelo Autor.

Colormaps uniformes perceptualmente

Colormaps como inferno e plasma oferecem melhor visibilidade em diferentes meios de exibição.

# Gerar dados de elevação sintéticos 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 # Dados de elevação # Plotar os dados de elevação usando o colormap 'plasma' plt.contourf(X, Y, Z, cmap='plasma') # Adicionar uma barra de cores plt.colorbar(label='Elevation (m)') # Adicionar título e rótulos plt.title('Topographic Map (Plasma Colormap)') plt.xlabel('X Coordinate') plt.ylabel('Y Coordinate') # Exibir o gráfico plt.show()

Exemplo de visualização de colormap perceptualmente uniforme do Matplotlib. Imagem do Autor.

Criando e Modificando Colormaps do Matplotlib

Embora o Matplotlib tenha uma ampla variedade de colormaps内置, há cenários onde você desejaria personalizar suas cores. As ferramentas chave para criar colormaps personalizados no Matplotlib são ListedColormap e LinearSegmentedColormap.

Criando um colormap personalizado com ListedColormap

ListedColormap permite criar um colormap a partir de uma lista de cores específicas. Este método é útil ao atribuir cores específicas a categorias distintas em dados categóricos. 

from matplotlib.colors import ListedColormap Dados categóricos categories = ['Category A', 'Category B', 'Category C', 'Category D'] values = [25, 40, 35, 30] Lista de cores personalizadas para o colormap (por exemplo, tons de azul, verde, vermelho e púrpura) custom_colors = ['#1f77b4', '#2ca02c', '#d62728', '#9467bd'] Criar um ListedColormap usando as cores personalizadas custom_cmap = ListedColormap(custom_colors) Definir o tamanho da figura plt.figure(figsize=(8, 6)) Criar um gráfico de barras com o colormap personalizado bars = plt.bar(categories, values, color=custom_cmap.colors) Adicionar um título plt.title('Bar Chart with Custom ListedColormap') Rotular os eixos plt.xlabel('Categories') plt.ylabel('Values') Exibir o gráfico plt.show()

Matplotlib colormap personalizado com ListedColormap. Imagem pelo Autor.

Criando um colormap personalizado com LinearSegmentedColormap

LinearSegmentedColormap permite criar colormaps que transicionam suavemente entre cores. Isso é útil porque os dados contínuos frequentemente requerem mudanças degradê de cor. Aqui, também estou especificando o número de intervalos que quero para minha visualização.

from matplotlib.colors import LinearSegmentedColormap # Criar uma grelha de valores para uma função 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 um mapa de cores personalizado que transita do azul para o branco e para o vermelho colors = ['blue', 'white', 'red'] custom_cmap = LinearSegmentedColormap.from_list('blue_white_red', colors) # Ajustar o número de classes de cores (níveis discretos) # Especificar o número de níveis (ex, 10 para 10 bandas de cores distintas) num_classes = 10 levels = np.linspace(Z.min(), Z.max(), num_classes) # Definir o tamanho da figura plt.figure(figsize=(8, 6)) # Traçar a função Gaussiana 2D com o mapa de cores ajustado contour = plt.contourf(X, Y, Z, levels=levels, cmap=custom_cmap) # Adicionar uma barra de cores para mostrar as classes de cores discretas classes de cores discretas plt.colorbar(contour, label='Gaussian Function Value') # Adicionar rótulos para os eixos plt.xlabel('X') plt.ylabel('Y') # Adicionar um título plt.title(f'2D Gaussian with {num_classes} Discrete Color Classes') # Exibir o gráfico plt.show()

Matplotlib custom ajustando o número de classes de cores. Imagem do autor.

Personalização de intervalos de cores e intensidade

Você pode controlar a intensidade ou o intervalo de cores em uma colormap existente manipulando sua normalização ou fatiando-a para usar um subconjunto das cores disponíveis. No exemplo a seguir, os intervalos de cores são fatiados para mostrar temperaturas entre 16 e 40 graus Celsius.

# Configurar o gráfico para o mapa de calor plt.figure(figsize=(12, 8)) # Definir uma normalização personalizada para o intervalo de temperatura norm = mcolors.Normalize(vmin=16, vmax=40) # Criar o mapa de calor com uma colormap sequencial heatmap = plt.imshow(monthly_temperature_table, cmap='YlOrRd', aspect='auto', norm=norm) # Adicionar a barra de cores para representar a temperatura colorbar = plt.colorbar(heatmap, orientation='horizontal') colorbar.set_label('Temperature (°C)', labelpad=10) # Nomear os eixos plt.xlabel('Day of the Month') plt.ylabel('Month') # Definir os ticks do eixo y para exibir nomes de meses em vez de números plt.yticks(ticks=np.arange(len(month_names)), labels=month_names) # Adicionar um título ao mapa de calor plt.title('Monthly Temperature Heatmap (Sequential Colormap)') # Exibir o gráfico plt.grid(False) plt.show()

Customização de intervalos de cores e intensidade no Matplotlib. Imagem do Autor.

Combinando colormaps existentes

Você também pode combinar colormaps existentes misturando múltiplas colormaps para criar visualizações mais complexas.

from matplotlib.colors import LinearSegmentedColormap, Normalize # Criar dados sintéticos de elevação x = np.linspace(-180, 180, 500) # Longitude y = np.linspace(-90, 90, 250) # Latitude X, Y = np.meshgrid(x, y) Z = 5000 * np.sin(np.sqrt(X**2 + Y**2) * np.pi / 180) # Dados sintéticos de elevação # Definir as colormaps base ('viridis' e 'cividis') cmap1 = plt.get_cmap('viridis') cmap2 = plt.get_cmap('cividis') # Criar uma colormap personalizada misturando as duas 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) # Criar a colormap misturada custom_cmap = blend_colormaps(cmap1, cmap2, blend_ratio=0.5) # Normalizar os dados para visualização norm = Normalize(vmin=-5000, vmax=5000) # Definir o tamanho da figura plt.figure(figsize=(12, 6)) # Plotar os dados sintéticos de elevação com a colormap misturada contour = plt.contourf(X, Y, Z, levels=100, cmap=custom_cmap, norm=norm) # Adicionar uma barra de cores para mostrar o mapeamento de cores misturadas plt.colorbar(contour, label='Elevation (meters)') # Adicionar rótulos para os eixos plt.xlabel('Longitude') plt.ylabel('Latitude') # Adicionar um título plt.title('Geographical Elevation Data with Blended Colormap (Viridis + Cividis)') # Exibir o gráfico plt.show()

Matplotlib Combinando colormaps existentes. Imagem do Autor.

Invertendo colormaps usando o sufixo _r

Você pode inverter qualquer colormap no Matplotlib adicionando o sufixo _r no seu nome.

# Configurar o gráfico para o heatmap plt.figure(figsize=(12, 8)) # Criar uma normalização personalizada para o intervalo de cores norm = mcolors.Normalize(vmin=16, vmax=40) # Plotar o heatmap usando imshow com o colormap sequencial im = plt.imshow(monthly_temperature_table, cmap='YlOrRd_r', norm=norm, aspect='equal') # Adicionar uma barra de cores com orientação horizontal cbar = plt.colorbar(im, orientation='horizontal', pad=0.1) cbar.set_label('Temperature (°C)', labelpad=10) # Adicionar rótulos para os eixos plt.xlabel('Day of the Month') plt.ylabel('Month') # Definir os ticks do eixo y para exibir nomes de meses em vez de números plt.yticks(ticks=np.arange(len(month_names)), labels=month_names) # Adicionar um título plt.title('Temperature Heatmap (Sequential Colormap)') # Exibir o gráfico plt.show()

Matplotlib Invertendo colormaps usando o sufixo _r. Imagem do Autor.

Tratamento de Erros Comuns em Colormaps do Matplotlib

Quando trabalha com mapas de cores no Matplotlib, pode encontrar erros que afetam seu fluxo de trabalho. A seguir estão alguns desses erros e como solucioná-los.

AttributeError: o módulo ‘matplotlib’ não tem o atributo ‘colormaps’

Este erro ocorre quando você usa versões do Matplotlib anteriores a 3.4.0 para acessar matplotlib.colormaps. O atributo colormaps foi introduzido no Matplotlib 3.4.0. Primeiro, verifique sua versão do Matplotlib usando o código abaixo para solucionar esse erro.

import matplotlib print(matplotlib.__version__)

Atualize usando o seguinte comando pip.

pip install --upgrade matplotlib

Se você encontrar problemas ao atualizar sua versão do Matplotlib, tente o seguinte método para acessar mapas de cores.

plt.get_cmap('viridis') # em vez de matplotlib.colormaps['viridis']

Atribuição incorreta de cores

Você pode experimentar atribuições de cor incorretas ao passar um valor fora do intervalo esperado ou quando a paleta de cores é aplicada incorretamente. A atribuição incorreta de cor também pode surgir se a paleta de cores é destinada a dados contínuos, mas é aplicada a dados categóricos ou vice-versa.

Para garantir que seus dados estejam dentro do intervalo esperado, sempre normalize ou escalone-os usando os parâmetros vmax e vmin.

import matplotlib.colors as mcolors # Crie um conjunto de dados de temperatura de exemplo data = np.random.rand(10, 10) * 100 # Ajuste o intervalo para corresponder aos seus dados # Crie uma instância de normalização de cor para escalonar os dados ao intervalo da paleta de cores norm = mcolors.Normalize(vmin=0, vmax=100) # Crie um mapa de calor usando a paleta de cores 'viridis' e a normalização especificada plt.imshow(data, cmap='viridis', norm=norm, interpolation='nearest') plt.colorbar() plt.show()

Para um controle mais fino, você pode definir explicitamente os limites de cor usando os parâmetros boundaries ou norm nas funções de plotagem.

Artifacts visuais e resultados inesperados

Quando se trabalha com dados discretos ou de baixa resolução, pode-se experimentar faixas de cor indesejadas, contraste excessivo ou sangramento de cor. O problema ocorre quando seus dados têm um intervalo limitado, mas são exibidos com uma colormap contínua.

Para resolver esse problema, use mais pontos de dados ou ajuste o número de níveis de cor para suavizar as transições.

# Aumente o número de bins na colormap cmap = plt.get_cmap('viridis', 256) plt.imshow(data, cmap=cmap)

Você pode dividir a colormap em níveis fixos para lidar com dados discretos, quando apropriado.

cmap = plt.get_cmap('inferno', 10) # Divida a colormap em 10 níveis discretos plt.imshow(data, cmap=cmap)

Também pode verificar as configurações de exibição e ajustar a resolução, especialmente ao salvar as visualizações, para evitar gráficos de baixa resolução

plt.savefig('plot.png', dpi=300) # Salve a figura com uma resolução mais alta

Distorção de cor devido ao clipping

Distorção de cor ocorre quando os dados contêm valores extremos fora do intervalo de cor esperado. Isso faz com que partes dos dados sejam cortadas e atribuídas a cor mínima ou máxima no colormap.

Para evitar a distorção de cor, ajuste os limites de cor usando vmin e vmax para corresponder ao intervalo dos seus dados, prevenindo o corte.

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

Você também deve usar escalonamento robusto para lidar com valores atípicos, definindo limites personalizados que excluem valores extremos.

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

Colormap não está sendo exibido corretamente em gráficos 3D

Se há um problema com como os dados são mapeados na superfície 3D, os colormaps podem não mostrar corretamente nas visualizações 3D. Para resolver, certifique-se de que os dados do eixo z estão normalizados para se encaixar dentro do intervalo esperado do colormap. Além disso, use os limites apropriados do colormap para capturar o intervalo completo dos valores z.

from mpl_toolkits.mplot3d import Axes3D # Gerar dados de exemplo para um gráfico de superfície 3D X, Y = np.meshgrid(np.linspace(-5, 5, 50), np.linspace(-5, 5, 50)) Z = np.sin(np.sqrt(X**2 + Y**2)) # Criar um objeto de eixos 3D ax = plt.axes(projection='3d') # Plotar a superfície usando a paleta de cores 'viridis' e ajustando os limites de cor ax.plot_surface(X, Y, Z, cmap='viridis', vmin=np.min(Z), vmax=np.max(Z)) plt.show()

Conclusão

Escolher a paleta de cores certa é um passo importante, pois realmente afeta como os usuários veem e entendem seus dados. Na minha opinião, gastar muito tempo com análise de dados e ser descuidado na etapa final, que é a parte onde você comunica seus achados, é um grande erro.

Felizmente, o Matplotlib oferece muitas opções para garantir que seus visuaiscontem uma história convincente. Inscreva-se em nosso curso, Introdução à Visualização de Dados com Matplotlib, para se tornar um especialista. E se você é um usuário de Python que também usa Seaborn para visualização (é ótimo conhecer ambos), leia nosso Guia Rápido para Escolher Cores no Seaborn e complemente com nosso Introdução à Visualização de Dados com Seaborn curso.

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