Python 如何将颜色代码添加到seaborn热图上的yticklabels?

Python 如何将颜色代码添加到seaborn热图上的yticklabels?,python,pandas,matplotlib,colors,seaborn,Python,Pandas,Matplotlib,Colors,Seaborn,我有一个基因表达和细胞的矩阵,我想把它们显示为热图,这本身不是问题。然而,将所有的基因显示为YtickLabel将过于混乱,视觉上也不吸引人。因此,我将每个基因注释为属于一个特定的功能组,并希望将每个功能组表示为一种颜色,并在热图上显示它们的颜色,顺序与基因出现的顺序相同。我只是想澄清一下,我不想按颜色对它们进行分组,我相信你可以使用seaborn clustermap进行分组 因此,到目前为止,我有一个熊猫数据框架,它包含了基因及其各自的功能组和细胞的多索引 我在Stackoverflow和G

我有一个基因表达和细胞的矩阵,我想把它们显示为热图,这本身不是问题。然而,将所有的基因显示为YtickLabel将过于混乱,视觉上也不吸引人。因此,我将每个基因注释为属于一个特定的功能组,并希望将每个功能组表示为一种颜色,并在热图上显示它们的颜色,顺序与基因出现的顺序相同。我只是想澄清一下,我不想按颜色对它们进行分组,我相信你可以使用seaborn clustermap进行分组

因此,到目前为止,我有一个熊猫数据框架,它包含了基因及其各自的功能组和细胞的多索引

我在Stackoverflow和Google上搜索了很多答案,但没有找到任何运气。这是我第一次尝试这类事情,所以不幸的是我不知道从哪里开始

因此,为了简单起见,假设您有以下数据帧:

import seaborn as sns
import numpy as np
import pandas as pd

data=pd.DataFrame(np.array([(0,1,2),(4,5,6),(7,8,9)]), columns=['C1','C2','C3'], index=pd.MultiIndex.from_arrays([['Gene1','Gene2','Gene3'],['A','B','A']]))
这将产生以下结果:

           C1  C2  C3
Gene1   A   0   1   2
Gene2   B   4   5   6
Gene3   A   7   8   9

现在,我可以简单地调用sns.heatmapdata来生成热图。然而,我如何定制它,使我得到代表A&B而不是Gene1、Gene2、Gene3的颜色作为标签?例如,假设A是蓝色的,B是绿色的,我希望它从顶部->底部将yticklabels显示为蓝色、绿色、蓝色


非常感谢。

这里有一个可能的解决方案,可以创建一个新的轴,位于热图的左侧,它显示另一个基于第二个多索引级别的值的热图

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

data=pd.DataFrame(np.array([(0,1,2),(4,5,6),(7,8,9)]), 
                  columns=['C1','C2','C3'], 
                  index=pd.MultiIndex.from_arrays([['Gene1','Gene2','Gene3'],['A','B','A']]))


cats = data.index.to_frame().set_index(0)
u, inv = np.unique(cats.values, return_inverse=True)

colors = ["navy", "limegreen", "gold"]
assert(len(u) <= len(colors))

cmap = mcolors.ListedColormap(colors)
norm = mcolors.BoundaryNorm(np.arange(len(u)+1)-.5, len(u))

fig, (sax, hax) = plt.subplots(ncols=2, sharey=True,
                               gridspec_kw=dict(width_ratios=[1, data.shape[1]]))

im = sax.imshow(np.atleast_2d(inv).T, cmap=cmap, norm=norm)
hax.imshow(data.values, cmap="Greys")

sax.set_yticks(np.arange(len(cats)))
sax.set_yticklabels(cats.index)
sax.tick_params(bottom=False, labelbottom=False)

hax.set_xticks(np.arange(len(data.columns)))
hax.set_xticklabels(data.columns)

cbar = fig.colorbar(im, cax = fig.add_axes([.125, .08, .1, .04]), 
                    orientation="horizontal", ticks=np.arange(len(u)))
cbar.set_ticklabels(u)

plt.show()

我想我不明白预期的结果。是否要更改文本颜色,使Gene1以蓝色显示?或者,是否要在开始处添加另一列,以显示相应颜色的像素?或者完全不同的东西?不,不是文字颜色。它更接近后者。我基本上想要一个颜色条,也许这就是他们所说的,并列在热图上的每个功能组的代表。这只是我从谷歌得到的一个随机示例,但我想要的是与这张图片中的分类侧栏相同的东西:乍一看,这似乎正是我想要的。我将在今天晚些时候详细研究它,并回复您,说明它是否对我有效。提前多谢!谢谢,这给我打下了坚实的基础。我只需要调整它以适应更大范围的数据。这也是一个很好的起点,它不太依赖seaborn,而是使用matplotlib从头开始。非常感谢。你能解释一下为什么你把边界规范设为np.arangelenu+1-.5而不是仅仅把它作为np.arangelenu吗?我看不出在产出方面有什么不同。我认为它可能不包括端点,因此以1为增量将范围从-0.5到5.5,以确保1、2、3、4、5分别映射到一种颜色,但后者似乎仍然是这样。此外,如果数据集很大,那么使用它来减少计算时间是否有意义?即使我去掉norm-kwarg,结果也是一样的。是的,只有两个类别,它总是匹配的;但它应该是任何类别的通用解决方案。对不起,我没有提到,在我的实际数据中,我有6个类别,因此特别有这些范围。在哪些情况下,它将不匹配?更一般地说,我的问题是,如果BoundaryNorm从0到但不包括1,然后从1到但不包括2等等,类似于range的工作方式。