类似热图的图,但适用于seaborn中的分类变量 [英] heatmap-like plot, but for categorical variables in seaborn

查看:62
本文介绍了类似热图的图,但适用于seaborn中的分类变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题:有没有更简洁的方法来制作这个热图?如果没有,这可能是一个值得实现的功能,在这种情况下,我会将其发布在seaborn问题跟踪器上.

解决方案

您可以使用离散颜色图并修改颜色栏,而不是使用图例.

value_to_int = {j:i for i,j in enumerate(pd.unique(df.values.ravel()))} # 像你一样n = len(value_to_int)# 离散颜色图(来自给定 cmap 的 n 个样本)cmap = sns.color_palette("Pastel2",n)ax = sns.heatmap(df.replace(value_to_int),cmap = cmap)#修改颜色条:colorbar = ax.collections[0].colorbarr = colorbar.vmax-colorbar.vmincolorbar.set_ticks([colorbar.vmin + r/n * (0.5 + i) for i in range(n)])colorbar.set_ticklabels(list(value_to_int.keys()))plt.show()

颜色栏部分改编自此答案

HTH

Same question as heatmap-like plot, but for categorical variables but using python and seaborn instead of R:

Imagine I have the following dataframe:

df = pd.DataFrame({"John":"No Yes Maybe".split(),
                   "Elly":"Yes Yes Yes".split(),
                   "George":"No Maybe No".split()},
                   index="Mon Tue Wed".split())

Now I would like to plot a heatmap and color each cell by its corresponding value. That is "Yes", "No", "Maybe", for instance becomes "Green", "Gray", "Yellow". The legend should have those three colors and the corresponding values.

I solved this problem myself in the following manner. I can't seem to pass a categorical color map to seaborn's heatmap, so instead I replace all text by numbers and reconstruct the color map used by seaborn internally afterwards i.e.:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.patches as mpatches

# create dictionary with value to integer mappings
value_to_int = {value: i for i, value in enumerate(sorted(pd.unique(df.values.ravel())))}

f, ax = plt.subplots()
hm = sns.heatmap(df.replace(value_to_int).T, cmap="Pastel2", ax=ax, cbar=False)
# add legend
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.7, box.height])
legend_ax = f.add_axes([.7, .5, 1, .1])
legend_ax.axis('off')
# reconstruct color map
colors = plt.cm.Pastel2(np.linspace(0, 1, len(value_to_int)))
# add color map to legend
patches = [mpatches.Patch(facecolor=c, edgecolor=c) for c in colors]
legend = legend_ax.legend(patches,
    sorted(value_to_int.keys()),
    handlelength=0.8, loc='lower left')
for t in legend.get_texts():
    t.set_ha("left")

My question: is there a more succinct way of making this heatmap? If not, this might be a feature worth implementing in which case I'll post it on the seaborn issue tracker.

解决方案

You can use a discrete colormap and modify the colorbar, instead of using a legend.

value_to_int = {j:i for i,j in enumerate(pd.unique(df.values.ravel()))} # like you did
n = len(value_to_int)     
# discrete colormap (n samples from a given cmap)
cmap = sns.color_palette("Pastel2", n) 
ax = sns.heatmap(df.replace(value_to_int), cmap=cmap) 
# modify colorbar:
colorbar = ax.collections[0].colorbar 
r = colorbar.vmax - colorbar.vmin 
colorbar.set_ticks([colorbar.vmin + r / n * (0.5 + i) for i in range(n)])
colorbar.set_ticklabels(list(value_to_int.keys()))                                          
plt.show()

The colorbar part is adapted from this answer

HTH

这篇关于类似热图的图,但适用于seaborn中的分类变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆