Estou tentando fazer uma barra de cores discreta para um gráfico de dispersão em matplotlib
Eu tenho meus dados x, y e para cada ponto um valor de tag inteiro que desejo ser representado com uma cor única, por exemplo
plt.scatter(x, y, c=tag)
normalmente, a tag será um número inteiro de 0-20, mas o intervalo exato pode mudar
até agora, usei apenas as configurações padrão, por exemplo
plt.colorbar()
o que dá uma gama contínua de cores. Idealmente, eu gostaria de um conjunto de n cores discretas (n = 20 neste exemplo). Ainda melhor seria obter um valor de tag de 0 para produzir uma cor cinza e 1-20 para ser colorido.
Eu encontrei alguns scripts de 'livro de receitas', mas eles são muito complicados e não consigo pensar que sejam a maneira certa de resolver um problema aparentemente simples
fonte
Respostas:
Você pode criar uma barra de cores discreta personalizada com bastante facilidade usando um BoundaryNorm como normalizador para sua dispersão. A parte peculiar (no meu método) é fazer 0 aparecer como cinza.
Para imagens, costumo usar cmap.set_bad () e converter meus dados em um array mascarado numpy. Seria muito mais fácil tornar 0 em cinza, mas não consegui fazer isso funcionar com o scatter ou o cmap personalizado.
Como alternativa, você pode fazer seu próprio cmap do zero ou ler um existente e substituir apenas algumas entradas específicas.
Eu pessoalmente acho que com 20 cores diferentes é um pouco difícil de ler o valor específico, mas isso depende de você, é claro.
fonte
plt.colorbar.ColorbarBase
lança Erro. Usompl.colorbar.ColorbarBase
N-1
emcmap = mpl.colors.LinearSegmentedColormap.from_list('Custom cmap', cmaplist, cmap.N-1)
. Caso contrário, as cores não são distribuídas igualmente nas caixas e você tem um problema de barreira de cerca.q=np.arange(0.0, 1.01, 0.1) cmap = mpl.cm.get_cmap('jet') cmaplist = [cmap(x) for x in q] cmap = mpl.colors.LinearSegmentedColormap.from_list('Custom cmap', cmaplist, len(q)-1) norm = mpl.colors.BoundaryNorm(q, cmap.N)
N-1
, talvez você esteja certo, mas não posso replicar com meu exemplo. Você pode evitar oLinearSegmentedColormap
(e seuN
argumento) usando umListedColormap
. Os documentos melhoraram muito desde 13, consulte por exemplo: matplotlib.org/3.1.1/tutorials/colors/…Você pode seguir este exemplo :
que produz a seguinte imagem:
fonte
As respostas acima são boas, exceto pelo fato de não terem uma marcação adequada na barra de cores. Gosto de ter marcações no meio da cor para que o mapeamento de número -> cor seja mais claro. Você pode resolver esse problema alterando os limites da chamada matshow:
fonte
set_ticklabels(...)
só deve ser usado para controlar a formatação da etiqueta (por exemplo, número decimal, etc.). Se os dados forem realmente discretos, você pode não notar nenhum problema. Se houver ruído no sistema (por exemplo, 2 -> 1,9), essa rotulagem inconsistente resultará em uma barra de cores enganosa e incorreta.Para definir valores acima ou abaixo da faixa do mapa de cores, você vai querer usar os métodos
set_over
eset_under
do mapa de cores. Se você quiser sinalizar um valor específico, mascare-o (ou seja, crie uma matriz mascarada) e use oset_bad
método. (Dê uma olhada na documentação da classe de mapa de cores base: http://matplotlib.org/api/colors_api.html#matplotlib.colors.Colormap )Parece que você quer algo assim:
fonte
Este tópico já está bem coberto, mas eu queria adicionar algo mais específico: eu queria ter certeza de que um determinado valor seria mapeado para aquela cor (não para qualquer cor).
Não é complicado mas como demorou algum tempo, poderá ajudar outras pessoas a não perderem tanto tempo como eu :)
fonte
pos
não tenho a certeza do porque está aqui mas é pedido pelo FuncFormatter () ... Talvez outra pessoa possa nos esclarecer sobre isso!Tenho investigado essas idéias e aqui estão meus cinco centavos. Ele evita chamar
BoundaryNorm
e também especificarnorm
como um argumento parascatter
ecolorbar
. No entanto, não encontrei maneira de eliminar a longa chamada paramatplotlib.colors.LinearSegmentedColormap.from_list
.Alguns antecedentes são que matplotlib fornece os chamados mapas de cores qualitativos, destinados ao uso com dados discretos.
Set1
, por exemplo, tem 9 cores facilmente distinguíveis etab20
pode ser usado para 20 cores. Com esses mapas, pode ser natural usar suas primeiras n cores para colorir gráficos de dispersão com n categorias, como faz o exemplo a seguir. O exemplo também produz uma barra de cores com n cores discretas adequadamente rotuladas.que produz a imagem abaixo. O
n
na chamada paraSet1
especifica as primeirasn
cores desse mapa de cores e o últimon
na chamada parafrom_list
especifica a construção de um mapa comn
cores (o padrão é 256). Para definircm
como o mapa de cores padrão complt.set_cmap
, achei necessário dar um nome e registrá-lo, a saber:fonte
Acho que você gostaria de dar uma olhada em colors.ListedColormap para gerar seu mapa de cores ou, se precisar apenas de um mapa de cores estático, estou trabalhando em um aplicativo que pode ajudar.
fonte