【发布时间】:2016-07-13 15:42:10
【问题描述】:
与heatmap-like plot, but for categorical variables 相同的问题,但使用 python 和 seaborn 而不是 R:
假设我有以下数据框:
df = pd.DataFrame({"John":"No Yes Maybe".split(),
"Elly":"Yes Yes Yes".split(),
"George":"No Maybe No".split()},
index="Mon Tue Wed".split())
现在我想绘制一个热图并根据每个单元格的相应值着色。即“Yes”、“No”、“Maybe”,例如变成“Green”、“Gray”、“Yellow”。图例应该有这三种颜色和相应的值。
我自己通过以下方式解决了这个问题。我似乎无法将分类颜色图传递给 seaborn 的热图,因此我用数字替换所有文本,然后在内部重建 seaborn 使用的颜色图,即:
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")
我的问题:有没有更简洁的方法来制作这个热图?如果没有,这可能是一个值得实现的功能,在这种情况下,我会将其发布在 seaborn 问题跟踪器上。
【问题讨论】:
-
我添加了
value_to_int变量。现在还包括所有导入,因此您应该能够复制+粘贴代码。我的第一个问题仍未解决。图例并不总是显示正确的颜色映射值 -
我最近遇到了类似的情况,您的图例看起来比正常的颜色条要好得多。关于简化,
pandas.factorize为您提供值的整数和图例的列表。 -
查看这个 seaborn 包装:github.com/schlegelp/catheat
标签: python matplotlib seaborn