【问题标题】:Centering a table with a heatmap使用热图居中表格
【发布时间】:2021-06-23 19:27:01
【问题描述】:

我正在尝试在 seaborn 热图下添加一个 matplotlib 表。 我已经能够绘制它们,但对齐没有运气。

# Main data
df = pd.DataFrame({"A": [20, 10, 7, 39], 
                   "B": [1, 8, 12, 9], 
                   "C": [780, 800, 1200, 250]})

# It contains min and max values for the df cols
df_info =  pd.DataFrame({"A": [22, 35], 
                   "B": [5, 10], 
                   "C": [850, 900]})

df_norm = (df - df.min())/(df.max() - df.min())


# Plot the heatmap
vmin = df_norm.min().min()
vmax = df_norm.max().max()

fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)
sns.heatmap(df_norm, ax=ax1, annot=df, cmap='RdBu_r', cbar=True)

当我将表格添加到 ax2 时,它会绘制热图的所有宽度(包括彩条)。我已经尝试了 locbbox 的所有可能组合,但我无法将表格准确居中并为其提供与热图相同的宽度(整个表格的宽度以及单个单元格的宽度)顶。

table = df_info
cell_text = []
for row in range(len(table)):
    cell_text.append(table.iloc[row])

ax2.axis('off')
ax2.table(cellText=cell_text,
          rowLabels=table.index,
          colLabels=None,
          loc='center')

有时我将参数square=True 传递给热图以打印平方单元格,结果是这样的:

问题:如何将表格及其单元格附加到热图中并将其居中?

编辑: 从技术上讲,tdy's answer 可以解决我的简单示例的问题。虽然我可能过度简化了它并遗漏了一条重要信息。
在我的真实案例场景中,如果我使用以下方式创建图形:

fig, (ax1, ax2) = plt.subplots(nrows=2,
                               **{"figsize": (18, 18),
                                  "dpi": 200,
                                  "tight_layout": True})

并应用上面提到的答案,我会得到这样的结果:

表格在底部远且比热图更宽的位置。

另外,如果我设置tight_layout=False,我会得到一个宽度正确但底部仍然很远的表格:

fig, (ax1, ax2) = plt.subplots(nrows=2,
                               **{"figsize": (18, 18),
                                  "dpi": 200,
                                  "tight_layout": False})

我猜在我的情况下,"figsize": (18, 18)tight_layout 对我的问题有很大影响,但我既不知道为什么也不知道如何解决它。

【问题讨论】:

    标签: python pandas matplotlib seaborn heatmap


    【解决方案1】:

    短方法

    您可以使用Axes.set_position() 移动/调整表格大小。 left/bottom/width/height 参数可以根据需要进行调整:

    bbox1 = ax1.get_position()
    bbox2 = ax2.get_position()
    
    # modify as needed
    left = bbox1.x0
    bottom = bbox1.y0 - (bbox2.height * 0.8)
    width = bbox1.x0 + (bbox1.width * 0.8)
    height = bbox2.height
    
    ax2.set_position([left, bottom, width, height])
    


    更长的方法

    如果简单的方法效果不佳,请尝试通过gridspec_kwplt.subplots() 中设置坐标轴height_ratios。我还需要设置tight_layout=False

    使用height_ratios 设置ax1:ax2(热图:表格)的比率,并使用*_offset 变量根据需要调整表格的大小/位置。这些值适用于我的系统,但您可以针对您的系统进行调整:

    ### modify these params as needed ###
    
    height_ratios = (20, 1) # heatmap:table ratio (20:1)
    left_offset = 0         # table left position adjustment
    bottom_offset = -0.025  # table bottom position adjustment
    width_offset = -0.0005  # table width adjustment
    height_offset = 0       # table height adjusment
    
    #####################################
    
    fig_kw = dict(figsize=(18, 18), dpi=200, tight_layout=False)
    gridspec_kw = dict(height_ratios=height_ratios)
    fig, (ax1, ax2) = plt.subplots(nrows=2, gridspec_kw=gridspec_kw, **fig_kw)
    
    sns.heatmap(df_norm, ax=ax1, annot=df, cmap='RdBu_r', cbar=True)
    ax2.table(cellText=[df_info.iloc[row] for row in range(len(df_info))],
              rowLabels=table.index,
              colLabels=None,
              loc='center')
    ax2.axis('off')
    
    bbox1 = ax1.get_position()
    bbox2 = ax2.get_position()
    
    left = bbox1.x0 + left_offset
    bottom = bbox1.y0 - bbox2.height + bottom_offset
    width = bbox1.width + width_offset
    height = bbox2.height + height_offset
    
    ax2.set_position([left, bottom, width, height])
    

    【讨论】:

    • 通过将此解决方案应用于我的简化示例确实有效。但在我的真实情况下,它没有,我不知道为什么。我尝试过使用set_positon 值,但桌子就在底部很远而且很宽,它既不会移动也不会调整大小:\
    • 嗯,没有亲眼看到,我想不出为什么会发生这种情况。如果你能建立一个可重现的例子,我可以看看。
    • @Leonardo 看看更新后的Longer version 是否有帮助。
    猜你喜欢
    • 1970-01-01
    • 2020-02-17
    • 2011-06-21
    • 1970-01-01
    • 2021-12-26
    • 2015-06-08
    • 2018-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多