【问题标题】:heatmap-like plot, but for categorical variables in seaborn类似热图的图,但适用于 seaborn 中的分类变量
【发布时间】: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


【解决方案1】:

我可能会为此目的使用散景,因为它内置了分类热图。Y 轴标签也水平书写,更具可读性。

http://docs.bokeh.org/en/0.11.1/docs/gallery/heatmap_chart.html

【讨论】:

    【解决方案2】:

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

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

    colorbar部分改编自this answer

    HTH

    【讨论】:

      猜你喜欢
      • 2012-10-11
      • 2015-12-27
      • 1970-01-01
      • 2021-07-24
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      • 1970-01-01
      • 2019-01-23
      相关资源
      最近更新 更多