Pergunta

Estou gerando um mapa de calor com dados que possuem um número discrepante fixo e preciso mostrar esses valores discrepantes como uma cor da paleta de cores do cmap que uso, que é "quente".Com o uso de cmap.set_bad('green') e np.ma.masked_values(data, outlier), obtenho um gráfico que parece correto, mas a barra de cores não está sendo sincronizada corretamente com os dados, mesmo se eu usar cmap.set_over ('verde').Aqui está o código que estou tentando:

plt.xlim(0,35)
plt.ylim(0,35)
img=plt.imshow(data, interpolation='none',norm=norm, cmap=cmap,vmax=outlier)

cb_ax=fig.add_axes([0.85, 0.1, 0.03, 0.8])

cb=mpl.colorbar.ColorbarBase(cb_ax,cmap=cmap,norm=norm,extend='both',spacing='uniform')
cmap.set_over('green')
cmap.set_under('green')

Aqui estão os dados (o valor discrepante é 1,69, obviamente):

Data;A;B;C;D;E;F;G;H;I;J;K    
A;1.2;0;0;0;0;1.69;0;0;1.69;1.69;0    
B;0;0;0;0;0;1.69;0;0;1.69;1.69;0    
C;0;0;0;0;0;1.69;0;0.45;1.69;1.69;0.92    
D;1;0;-0.7;-1.2;0;1.69;0;0;1.69;1.69;0    
E;0;0;0;0;0;1.69;0;0;1.69;1.69;0    
F;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69    
G;0;0;0;0;0;1.69;0;0;1.69;1.69;0    
H;0;0;0;0;0;1.69;0;0;1.69;1.69;0    
I;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69
J;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69
K;0;0;0;0;0;1.69;0;0;1.69;1.69;0

Agradeço qualquer ajuda

Foi útil?

Solução

O que está acontecendo é que você está usando um array mascarado onde os valores discrepantes estão mascarados.

Portanto, eles não aparecem na barra de cores como "acabados".(ou seja,no que diz respeito ao matplotlib, os valores mascarados são inválidos, não ultrapassam o limite)

Como exemplo independente para reproduzir seu problema:

import numpy as np
import matplotlib.pyplot as plt

threshold = 0.8
data = np.random.random((10,10))
data = np.ma.masked_greater(data, threshold)

fig, ax = plt.subplots()
im = ax.imshow(data, cmap=plt.cm.hot, interpolation='none')
cbar = fig.colorbar(im, extend='max')
cbar.cmap.set_over('green')

plt.show()

enter image description here

Se simplesmente não transformarmos isso em um array mascarado e, em vez disso, especificarmos o vmax kwarg para imshow:

import numpy as np
import matplotlib.pyplot as plt

threshold = 0.8
data = np.random.random((10,10))

fig, ax = plt.subplots()
im = ax.imshow(data, cmap=plt.cm.hot, interpolation='none', vmax=threshold)
cbar = fig.colorbar(im, extend='max')
cbar.cmap.set_over('green')

plt.show()

enter image description here

Basicamente, esta é a diferença entre set_over (ou abaixo) e set_bad.

Se você ainda quiser usar um array mascarado, basta ligar cbar.cmap.set_bad('green') assim como set_over, e você obteria o efeito desejado (embora todos os valores "ruins", e não apenas aqueles acima do limite, fossem verdes).Se você seguir esse caminho, precisará especificar manualmente o vmax.Caso contrário, será considerado o máximo das porções não mascaradas do array.

Outras dicas

Eu acho que você precisa definir extend para "both" e alimentar em um Normalize objeto:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas

from io import StringIO # python 3
#from StringIO import StringIO # python 2

datastring = StringIO("""\
Data;A;B;C;D;E;F;G;H;I;J;K
A;1.2;0;0;0;0;1.69;0;0;1.69;1.69;0
B;0;0;0;0;0;1.69;0;0;1.69;1.69;0
C;0;0;0;0;0;1.69;0;0.45;1.69;1.69;0.92
D;1;0;-0.7;-1.2;0;1.69;0;0;1.69;1.69;0
E;0;0;0;0;0;1.69;0;0;1.69;1.69;0
F;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69
G;0;0;0;0;0;1.69;0;0;1.69;1.69;0
H;0;0;0;0;0;1.69;0;0;1.69;1.69;0
I;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69
J;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69;1.69
K;0;0;0;0;0;1.69;0;0;1.69;1.69;0
""")

threshold = 1.68
data = pandas.read_table(datastring, sep=';', index_col='Data')
cmap = mpl.cm.coolwarm
norm = mpl.colors.Normalize(vmin=-1 * threshold, vmax=threshold)
cmap.set_over('slategray')
cmap.set_under('forestgreen')

fig, ax = plt.subplots()
ax.set_aspect('equal')
cb_ax=fig.add_axes([0.85, 0.1, 0.03, 0.8])
img = ax.imshow(data, cmap=cmap, norm=norm, interpolation='none')
cb = mpl.colorbar.ColorbarBase(cb_ax, cmap=cmap, norm=norm, extend='both')

Me dá:enter image description here

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top