简体   繁体   English

一张 seaborn 热图中的两个范围/色阶

[英]Two ranges/ color-scales within one seaborn heatmap

I was doing quite some research, but couldn't find a satisfying solution yet.我做了很多研究,但还没有找到令人满意的解决方案。

I'm trying to build a heatmap using seaborn.我正在尝试使用 seaborn 构建热图。 As my dataset is a bit volatile in a lower range (0-20) but reaches up to 7000 using only one color-scale for all of the data doesn't allow a good graphical interpretation.由于我的数据集在较低范围(0-20)内有点不稳定,但对于所有数据仅使用一个色标即可达到 7000,因此无法进行良好的图形解释。 That's why I thought about using two scales, two different color-spectrums.这就是为什么我考虑使用两个尺度,两个不同的色谱。

I would like to merge those two heatmaps into one:我想将这两个热图合并为一个:

在此处输入图像描述

What works so far is that I get both axes (scales) displayed in my plot, but when it comes to plotting the data only the last active axis is taken into account.到目前为止有效的是,我的 plot 中显示了两个轴(刻度),但是在绘制数据时,只考虑最后一个活动轴。 The upper range is not considered.不考虑上限。

有两个尺度的热图 2 2

I have also tried to split the data set according to the spectrum, but this was not working.我也尝试根据频谱拆分数据集,但这不起作用。 Here is my code:这是我的代码:

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

If you want to plot both parts together, you can update the colormaps such that the "over" and the "under" color are set to invisible ("none").如果您想将 plot 两个部分放在一起,您可以更新颜色图,将“over”和“under”颜色设置为不可见(“none”)。 The "over" color is used for values that are larger than vmax . “over”颜色用于大于vmax的值。 The "under" color is used for values below vmin . “under”颜色用于低于vmin的值。

Optionally, you can set negative padding for the first colorbar to have both colorbars closer together.或者,您可以为第一个颜色条设置负填充,以使两个颜色条靠得更近。

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

具有两个不同颜色图的热图

You need to create the two Axes to plot beforehand, and then use the ax argument when calling sns.heatmap in order to tell seaborn which Axes should have which colormap.您需要预先创建 plot 的两个Axes ,然后在调用sns.heatmap时使用ax参数来告诉 seaborn 哪个Axes应该具有哪个颜色图。

Example (using mock data):示例(使用模拟数据):

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

Resulting figure:结果图:

在此处输入图像描述

You can create a Colormap class that uses both other Colormaps您可以创建一个同时使用其他颜色图的颜色图 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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM