определенные выбросы на тепловой карте — matplotlib

Я создаю тепловую карту с данными, которые имеют фиксированный номер выброса, и мне нужно показать эти выбросы как цвет из цветовой палитры cmap, который я использую, который является «горячим». С использованием cmap.set_bad('green') и np.ma.masked_values(data, outlier) я получаю график, который выглядит правильно, но цветная полоса не синхронизируется с данными должным образом, даже если я использую cmap.set_over ('зеленый'). Вот код, который я пытался:

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')

Вот данные (выброс, очевидно, 1,69):

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

Ценю любую помощь


person user2998764    schedule 27.02.2014    source источник
comment
Ответ Джо объясняет, что вам нужно делать. Я рекомендую следовать ему.   -  person Paul H    schedule 28.02.2014


Ответы (2)


Происходит то, что вы используете замаскированный массив, в котором замаскированы выбросы.

Поэтому они не отображаются на цветовой полосе как «завершенные». (т.е. что касается matplotlib, замаскированные значения недействительны, а не превышают порог)

В качестве отдельного примера для воспроизведения вашей проблемы:

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()

введите здесь описание изображения

Если мы просто не будем делать это замаскированным массивом, а вместо этого укажем vmax kwarg на 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()

введите здесь описание изображения

По сути, это разница между set_over (или младше) и set_bad.

Если вы все еще хотите использовать замаскированный массив, вы можете просто вызвать cbar.cmap.set_bad('green'), а также set_over, и вы получите желаемый эффект (хотя все «плохие» значения, а не только те, которые превышают порог, будут зелеными). Если вы выберете этот маршрут, вам нужно будет вручную указать vmax. В противном случае он будет принят как максимум немаскированных частей массива.

person Joe Kington    schedule 27.02.2014
comment
Я использовал vmax в качестве значения выброса, но результат остался прежним. Я отредактировал свой вопрос, включив в него код, который я сейчас запускаю, а также данные, с которыми я работаю! - person user2998764; 28.02.2014

Я думаю, вам нужно установить extend в "both" и передать объект Normalize:

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')

Дает мне: введите здесь описание изображения

person Paul H    schedule 27.02.2014
comment
Я добавил объект нормализации: norm = mpl.colors.Normalize(vmin=negative_outlier,vmax=outlier) cmap.set_over('green') img=plt.imshow(data, interpolation='none', cmap=cmap,norm= норма) cb=mpl.colorbar.ColorbarBase(cb_ax,cmap=cmap,norm=norm,extend='both',spacing='uniform') Но результат все тот же... пробел вместо зеленого - person user2998764; 28.02.2014
comment
НЕТ, это не так, он по-прежнему дает мне пробелы для всех выбросов вместо зеленого. Цветовая полоса фиксируется объектом нормы, но не тепловой картой. Мне все еще нужно использовать set_bad и свойства маскирования, чтобы заставить его работать. Не знаю, что не так, так как сгенерированная вами карта включает эти выбросы без set_bad.. (я отредактировал свой пост, чтобы включить упомянутые вами изменения) - person user2998764; 28.02.2014
comment
@user2998764 user2998764 ну, я увел вас так далеко, как только мог, не видя ваших данных. отредактируйте свой вопрос, чтобы включить его. - person Paul H; 28.02.2014
comment
@user2998764 user2998764 посмотри мой измененный ответ - person Paul H; 28.02.2014