带有多种配色方案的带注释热图

Posted

技术标签:

【中文标题】带有多种配色方案的带注释热图【英文标题】:Annotated heatmap with multiple color schemes 【发布时间】:2019-06-21 04:20:11 【问题描述】:

我有以下数据框,并希望在热图中使用不同的配色方案来区分每个“步骤”中的小数差异。

样本数据:

Sample  Step 2  Step 3  Step 4  Step 5  Step 6  Step 7  Step 8
A   64.847  54.821  20.897  39.733  23.257  74.942  75.945
B   64.885  54.767  20.828  39.613  23.093  74.963  75.928
C   65.036  54.772  20.939  39.835  23.283  74.944  75.871
D   64.869  54.740  21.039  39.889  23.322  74.925  75.894
E   64.911  54.730  20.858  39.608  23.101  74.956  75.930
F   64.838  54.749  20.707  39.394  22.984  74.929  75.941
G   64.887  54.781  20.948  39.748  23.238  74.957  75.909
H   64.903  54.720  20.783  39.540  23.028  74.898  75.911
I   64.875  54.761  20.911  39.695  23.082  74.897  75.866
J   64.839  54.717  20.692  39.377  22.853  74.849  75.939
K   64.857  54.736  20.934  39.699  23.130  74.880  75.903
L   64.754  54.746  20.777  39.536  22.991  74.877  75.902
M   64.798  54.811  20.963  39.824  23.187  74.886  75.895

我正在寻找的一个例子:

【问题讨论】:

您能更准确地说明您想要绘制的内容吗?? 请不要将数据发布为图像,不要被他人复制粘贴,这样更难玩...... @SpghttCd - 我有一些样本数据供人们使用。 【参考方案1】:

我的第一种方法是基于具有多个子图的图形。图的数量将等于数据框中的列数;地块之间的差距可以缩小到零:

cm = ['Blues', 'Reds', 'Greens', 'Oranges', 'Purples', 'bone', 'winter']
f, axs = plt.subplots(1, df.columns.size, gridspec_kw='wspace': 0)
for i, (s, a, c) in enumerate(zip(df.columns, axs, cm)):
    sns.heatmap(np.array([df[s].values]).T, yticklabels=df.index, xticklabels=[s], annot=True, fmt='.2f', ax=a, cmap=c, cbar=False)
    if i>0:
        a.yaxis.set_ticks([])

结果:

不确定这是否会带来有用的甚至自我描述的数据可视化,但这是您的选择 - 也许这有助于开始...


补充:

关于添加彩条:当然可以。但是 - 除了不知道您的数据背景和可视化的目的之外 - 我想就所有这些添加一些想法:

首先:将所有这些颜色条作为单独的一组条添加到热图的一侧或下方可能是可能的,但我发现读取数据已经非常困难,另外:你已经有了所有这些注释 - 我认为这一切都会搞砸。 此外:与此同时,@ImportanceOfBeingErnest 提供了关于该主题的如此漂亮的解决方案,这在 imo 中并没有太大意义。

第二:如果你真的想坚持热图的事情,也许分开并给每一列提供它的颜色条会更适合:

cm = ['Blues', 'Reds', 'Greens', 'Oranges', 'Purples', 'bone', 'winter']
f, axs = plt.subplots(1, df.columns.size, figsize=(10, 3))
for i, (s, a, c) in enumerate(zip(df.columns, axs, cm)):
    sns.heatmap(np.array([df[s].values]).T, yticklabels=df.index, xticklabels=[s], annot=True, fmt='.2f', ax=a, cmap=c)
    if i>0:
        a.yaxis.set_ticks([])
f.tight_layout()

但是,所有这些 - 我敢怀疑这是您数据的最佳可视化。当然,我不知道您想对这些图说什么、看到或找到什么,但这就是重点:如果可视化类型符合需求,我想我会知道(或者至少可以想象)。

例如: 一个简单的df.plot() 会导致

我觉得这比热图更能在十分之一秒内说明您的列的不同特征。

或者您是否明确表示每列均值的差异?

(df - df.mean()).plot()

... 或者它们周围每一列的分布?

(df - df.mean()).boxplot()

我想说的是:在你开始/必须解释任何事情之前,当一个情节开始讲述底层数据时,数据可视化变得强大......

【讨论】:

@SpghttCd- 你认为我可以将所有颜色条连同热图一起显示吗?【参考方案2】:

我想问题可以分成几个部分。

将具有不同颜色图的多个热图放入同一张图片中。这可以通过按列屏蔽完整数组来完成,通过imshow 分别绘制每个屏蔽数组并应用不同的颜色图。将概念形象化:

获取可变数量的不同颜色图。 Matplotlib 提供了大量的颜色图,但是,它们在亮度和饱和度方面通常非常不同。在这里,似乎希望有不同色调的颜色图,但饱和度和亮度相同。 一种选择是动态创建颜色图,选择n 不同(且等间距)的色调,并使用相同的饱和度和亮度创建颜色图。

为每列获取不同的颜色条。由于列中的值可能具有完全不同的比例,因此需要每列的颜色条来了解显示的值,例如在第一列中,最亮的颜色可能对应于值 1,而在第二列中,它可能对应于值 100。可以在 GridSpec 的轴内创建几个颜色条,它位于实际旁边热图轴。该网格规范​​的列数和行数将取决于数据框中的列数。

总的来说,这可能如下所示。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib.gridspec import GridSpec

def get_hsvcmap(i, N, rot=0.):
    nsc = 24
    chsv = mcolors.rgb_to_hsv(plt.cm.hsv(((np.arange(N)/N)+rot) % 1.)[i,:3])
    rhsv = mcolors.rgb_to_hsv(plt.cm.Reds(np.linspace(.2,1,nsc))[:,:3])
    arhsv = np.tile(chsv,nsc).reshape(nsc,3)
    arhsv[:,1:] = rhsv[:,1:]
    rgb = mcolors.hsv_to_rgb(arhsv)
    return mcolors.LinearSegmentedColormap.from_list("",rgb)


def columnwise_heatmap(array, ax=None, **kw):
    ax = ax or plt.gca()
    premask = np.tile(np.arange(array.shape[1]), array.shape[0]).reshape(array.shape)
    images = []
    for i in range(array.shape[1]):
        col = np.ma.array(array, mask = premask != i)
        im = ax.imshow(col, cmap=get_hsvcmap(i, array.shape[1], rot=0.5), **kw)
        images.append(im)
    return images

### Create some dataset
ind = list("ABCDEFGHIJKLM")
m = len(ind)
n = 8
df = pd.DataFrame(np.random.randn(m,n) + np.random.randint(20,70,n), 
                  index=ind, columns=[f"Step i" for i in range(2,2+n)])

### Plot data
fig, ax = plt.subplots(figsize=(8,4.5))

ims = columnwise_heatmap(df.values, ax=ax, aspect="auto")

ax.set(xticks=np.arange(len(df.columns)), yticks=np.arange(len(df)),
       xticklabels=df.columns, yticklabels=df.index)
ax.tick_params(bottom=False, top=False, 
               labelbottom=False, labeltop=True, left=False)

### Optionally add colorbars.
fig.subplots_adjust(left=0.06, right=0.65)
rows = 3
cols = len(df.columns) // rows + int(len(df.columns)%rows > 0)
gs = GridSpec(rows, cols)
gs.update(left=0.7, right=0.95, wspace=1, hspace=0.3)
for i, im in enumerate(ims):
    cax = fig.add_subplot(gs[i//cols, i % cols])
    fig.colorbar(im, cax = cax)
    cax.set_title(df.columns[i], fontsize=10)

plt.show()

【讨论】:

以上是关于带有多种配色方案的带注释热图的主要内容,如果未能解决你的问题,请参考以下文章

vim配色方案设置(更换vim配色方案)

xshell如何设置字体和背景色颜色?

IAR 编辑器配色方案

如何设置xshell的背景颜色

vim 配色方案

如何使用 React 使 Web 应用程序配色方案可变?