热力图上的特定异常值- matplotlib

5

我正在生成一个热图,其中数据具有固定的异常值数量,并且我需要将这些异常值显示为颜色,超出了我使用的cmap"hot"的颜色板。使用cmap.set_bad('green')和np.ma.masked_values(data, outlier),我可以得到一个看起来正确的图形,但是即使我使用cmap.set_over('green'),颜色条也无法与数据正确同步。下面是我一直在尝试的代码:

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

感激任何帮助


Joe的回答解释了你需要做什么。我建议你跟随他的建议。 - Paul H
2个回答

6
发生的情况是你在使用一个遮掩了离群点的掩膜数组。
因此,它们不会显示在色条上,被认为是“超标”。(即就 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()

enter image description here

如果我们不使用掩码数组,而是在imshow函数中指定vmax关键字参数:

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

基本上,这是 set_over(或 under)和 set_bad 之间的区别。

如果您仍想使用掩码数组,则可以调用 cbar.cmap.set_bad('green') 以及 set_over,然后就会得到您想要的效果(尽管所有“坏”值,而不仅仅是超过阈值的值,都将是绿色)。 如果您选择这条路线,您需要手动指定 vmax。否则,它将被视为数组未屏蔽部分的最大值。


我将vmax用作异常值,但输出结果仍然相同。我已经编辑了我的问题,包括我现在正在运行的代码以及我正在处理的数据! - user2998764

1

我认为您需要将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')

给我: 在此输入图片描述

我添加了normalize对象: norm = mpl.colors.Normalize(vmin=negative_outlier,vmax=outlier) cmap.set_over('green') img=plt.imshow(data, interpolation='none', cmap=cmap,norm=norm) cb=mpl.colorbar.ColorbarBase(cb_ax,cmap=cmap,norm=norm,extend='both',spacing='uniform') 但结果仍然相同...白色空间而不是绿色。 - user2998764
没有,它仍然为所有的异常值给出了白色空格,而不是绿色。颜色条使用norm对象固定,但热图没有。我仍然需要使用set_bad和masking属性来使其工作。不知道哪里出了问题,因为你生成的地图没有使用set_bad来处理这些异常值。(我已经编辑了我的帖子,包括你提到的更改) - user2998764
@user2998764,如果我没有看到您的数据,我已经为您做了尽可能多的事情。请编辑您的问题并将其包含在内。 - Paul H
@user2998764,请查看我的修改后的回复。 - Paul H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接