Gráfico de barras em matplotlib usando um mapa de cores
Eu tenho um df com duas colunas:
- y: diferentes valores numéricos para o eixo y
- dias: os nomes de quatro dias diferentes (segunda, terça, quarta, quinta)
Eu também tenho um mapa de cores com quatro cores diferentes que eu mesmo fiz e é um objeto ListedColorMap.
Quero criar um gráfico de barras com as quatro categorias (dias da semana) no eixo xe seus valores correspondentes no eixo y. Ao mesmo tempo, quero que cada barra tenha uma cor diferente usando meu mapa de cores.
Este é o código que usei para construir meu gráfico de barras:
def my_barchart(my_df, my_cmap):
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.bar(my_df['days'], my_df['y'], color=my_cmap)
return fig
No entanto, recebo o seguinte erro: "objeto do tipo 'ListedColormap' não tem len ()", então parece que não estou usando my_cmap corretamente.
Se eu remover isso da função e executá-lo, meu gráfico de barras parece ok, exceto que todas as barras têm a mesma cor. Portanto, minha pergunta é: qual é a maneira certa de usar um mapa de cores com um gráfico de barras?
Respostas
O colorargumento quer uma string ou um valor RGB [A] (pode ser uma única cor ou uma sequência de cores com uma para cada ponto de dados que você está plotando). Os mapas de cores normalmente podem ser chamados com flutuadores no intervalo [0, 1].
Portanto, o que você deseja fazer é pegar os valores que deseja para as cores de cada barra, escaloná-los no intervalo [0, 1] e, em seguida, chamar my_cmapcom esses valores redimensionados.
Então, digamos, por exemplo, que você queira que as cores correspondam aos valores y (alturas das barras), então você deve modificar seu código assim (presume que você tenha chamado import numpy as npanteriormente):
def my_barchart(my_df, my_cmap):
rescale = lambda y: (y - np.min(y)) / (np.max(y) - np.min(y))
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.bar(my_df['days'], my_df['y'], color=my_cmap(rescale(my_df['y'])))
return fig
Aqui está um exemplo mínimo independente de como usar o colorargumento com a saída de um cmap:
import matplotlib.pyplot as plt
import numpy as np
x = np.array([1, 2, 3])
y = np.array([4, 5, 6])
my_cmap = plt.get_cmap("viridis")
rescale = lambda y: (y - np.min(y)) / (np.max(y) - np.min(y))
plt.bar(x, y, color=my_cmap(rescale(y)))
plt.savefig("temp")
Resultado:
Ok, encontrei uma maneira de fazer isso sem precisar dimensionar meus valores:
def my_barchart(my_df, my_cmap):
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.bar(my_df['days'], my_df['y'], color=my_cmap.colors)
return fig
Basta adicionar .colorsdepois das my_cmapobras!