一个 seaborn 热图中的两个范围/色标
Two ranges/ color-scales within one seaborn heatmap
我做了很多研究,但还没有找到令人满意的解决方案。
我正在尝试使用 seaborn 构建热图。
由于我的数据集在较低范围 (0-20) 内有点不稳定,但在达到 7000 时仅对所有数据使用一个色标,无法进行良好的图形解释。这就是为什么我考虑使用两个尺度,两个不同的色谱。
我想将这两个热图合并为一个:
到目前为止有效的是我在我的绘图中显示了两个轴(刻度),但是在绘制数据时只考虑了最后一个活动轴。不考虑上限。
2
我也尝试过根据光谱拆分数据集,但这没有用。
这是我的代码:
df = pd.DataFrame(merged, classes)
vmax = np.amax(merged)
ax1 = sns.heatmap(df, vmin = 25, vmax = vmax, cmap = "crest", )
ax2 = sns.heatmap(df, vmin = 0, vmax = 25, cmap = "flare", )
plt.xlabel("Time")
plt.ylabel("Method")
plt.show()
你需要预先创建两个Axes
来绘制,然后在调用sns.heatmap
时使用ax
参数来告诉seaborn哪个Axes
应该有哪个颜色图。
示例(使用模拟数据):
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
values = np.random.uniform(0, 7000, size=(50, 50))
vmax = np.amax(values)
fig, (ax1, ax2) = plt.subplots(ncols=2)
sns.heatmap(values, ax=ax1, vmin=25, vmax=vmax, cmap="crest")
sns.heatmap(values, ax=ax2, vmin=0, vmax=25, cmap="flare")
for ax in (ax1, ax2):
ax.set_xlabel("Time")
ax.set_ylabel("Method")
plt.show()
结果图:
如果要将两个部分一起绘制,可以更新颜色图,将“上面”和“下面”的颜色设置为不可见 ("none")。 “over”颜色用于大于 vmax
的值。 “下方”颜色用于 vmin
.
以下的值
您可以选择为第一个颜色条设置负填充以使两个颜色条靠得更近。
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from scipy.ndimage.filters import gaussian_filter
# first create some test data
data = gaussian_filter(np.random.rand(50, 50), sigma=5)
data -= data.min()
data *= 2 / data.max()
data = np.where(data < 1, data*25, (data ** 3) * 25)
# adapt the colormaps such that the "under" or "over" color is "none"
cmap1 = plt.get_cmap('crest').copy()
cmap1.set_under('none')
cmap2 = plt.get_cmap('flare').copy()
cmap2.set_over('none')
ax1 = sns.heatmap(data, vmin=25, cmap=cmap1, cbar_kws={'pad': -0.02})
sns.heatmap(data, vmin=0, vmax=25, cmap=cmap2, ax=ax1)
plt.show()
您可以创建一个使用其他颜色图的颜色图class
import seaborn as sns
import matplotlib as mpl
import matplotlib.pyplot as plt
class SplitCMap(mpl.colors.Colormap):
def __init__(self, name, vmin, vsplit, vmax, N=256):
super().__init__(name, N)
self.lowcmap = mpl.cm.get_cmap('flare')
self.highcmap = mpl.cm.get_cmap('crest')
self.split_level = (vsplit-vmin) / (vmax-vmin)
self.scale_low = 1.0 / self.split_level
self.scale_high = 1.0 / (1.0 - self.split_level)
def mapcolor(self, v, **kwds):
if v < self.split_level:
return self.lowcmap(v * self.scale_low, **kwds)
return self.highcmap((v-self.split_level)*self.scale_high, **kwds)
def __call__(self, *args, **kwds):
if isinstance(args[0], (int, float)):
self.mapcolor(args[0], **kwds)
return [self.mapcolor(v, **kwds) for v in args[0] ]
df = pd.DataFrame(merged, classes)
vmax = np.amax(merged)
cmap = SplitCMap('split', 0, 25, vmax)
ax = sns.heatmap(df, cmap=cmap)
plt.xlabel("Time")
plt.ylabel("Method")
plt.show()
我做了很多研究,但还没有找到令人满意的解决方案。
我正在尝试使用 seaborn 构建热图。 由于我的数据集在较低范围 (0-20) 内有点不稳定,但在达到 7000 时仅对所有数据使用一个色标,无法进行良好的图形解释。这就是为什么我考虑使用两个尺度,两个不同的色谱。
我想将这两个热图合并为一个:
到目前为止有效的是我在我的绘图中显示了两个轴(刻度),但是在绘制数据时只考虑了最后一个活动轴。不考虑上限。
我也尝试过根据光谱拆分数据集,但这没有用。 这是我的代码:
df = pd.DataFrame(merged, classes)
vmax = np.amax(merged)
ax1 = sns.heatmap(df, vmin = 25, vmax = vmax, cmap = "crest", )
ax2 = sns.heatmap(df, vmin = 0, vmax = 25, cmap = "flare", )
plt.xlabel("Time")
plt.ylabel("Method")
plt.show()
你需要预先创建两个Axes
来绘制,然后在调用sns.heatmap
时使用ax
参数来告诉seaborn哪个Axes
应该有哪个颜色图。
示例(使用模拟数据):
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
values = np.random.uniform(0, 7000, size=(50, 50))
vmax = np.amax(values)
fig, (ax1, ax2) = plt.subplots(ncols=2)
sns.heatmap(values, ax=ax1, vmin=25, vmax=vmax, cmap="crest")
sns.heatmap(values, ax=ax2, vmin=0, vmax=25, cmap="flare")
for ax in (ax1, ax2):
ax.set_xlabel("Time")
ax.set_ylabel("Method")
plt.show()
结果图:
如果要将两个部分一起绘制,可以更新颜色图,将“上面”和“下面”的颜色设置为不可见 ("none")。 “over”颜色用于大于 vmax
的值。 “下方”颜色用于 vmin
.
您可以选择为第一个颜色条设置负填充以使两个颜色条靠得更近。
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from scipy.ndimage.filters import gaussian_filter
# first create some test data
data = gaussian_filter(np.random.rand(50, 50), sigma=5)
data -= data.min()
data *= 2 / data.max()
data = np.where(data < 1, data*25, (data ** 3) * 25)
# adapt the colormaps such that the "under" or "over" color is "none"
cmap1 = plt.get_cmap('crest').copy()
cmap1.set_under('none')
cmap2 = plt.get_cmap('flare').copy()
cmap2.set_over('none')
ax1 = sns.heatmap(data, vmin=25, cmap=cmap1, cbar_kws={'pad': -0.02})
sns.heatmap(data, vmin=0, vmax=25, cmap=cmap2, ax=ax1)
plt.show()
您可以创建一个使用其他颜色图的颜色图class
import seaborn as sns
import matplotlib as mpl
import matplotlib.pyplot as plt
class SplitCMap(mpl.colors.Colormap):
def __init__(self, name, vmin, vsplit, vmax, N=256):
super().__init__(name, N)
self.lowcmap = mpl.cm.get_cmap('flare')
self.highcmap = mpl.cm.get_cmap('crest')
self.split_level = (vsplit-vmin) / (vmax-vmin)
self.scale_low = 1.0 / self.split_level
self.scale_high = 1.0 / (1.0 - self.split_level)
def mapcolor(self, v, **kwds):
if v < self.split_level:
return self.lowcmap(v * self.scale_low, **kwds)
return self.highcmap((v-self.split_level)*self.scale_high, **kwds)
def __call__(self, *args, **kwds):
if isinstance(args[0], (int, float)):
self.mapcolor(args[0], **kwds)
return [self.mapcolor(v, **kwds) for v in args[0] ]
df = pd.DataFrame(merged, classes)
vmax = np.amax(merged)
cmap = SplitCMap('split', 0, 25, vmax)
ax = sns.heatmap(df, cmap=cmap)
plt.xlabel("Time")
plt.ylabel("Method")
plt.show()