缩放不同尺寸的热图以使单元格大小相等

时间:2017-09-24 21:19:38

标签: python matplotlib heatmap seaborn

我使用Python软件包Seaborn将矩阵绘制为PDF文档的热图,每个热图都在一个单独的页面上。热图具有相同的列数(在一次运行中相同,但通常不是常量)并且可能有不同的行数,因此PDF页面的大小不同。我希望在整个PDF文档中将热映射单元格成为相同大小的正方形。理想情况下,我会在绘制热图时明确指定单元格大小,但似乎没有这样的选项。我尝试按比例调整图表的行数和列数,但即使对于常量figure_widthfigure_height = cell_size * row_count,它也不会导致固定cell_size的单元格,而figure_width = cell_size * column_count并且figure_height = cell_size * row_count还会在热图的宽度和高度之间产生相互作用(因为单元格是正方形,即纵横比为1:1),结果比例变得更加模糊。

是否有任何解决方案可以明确指定seaborn.heatmap(或matplotlib colorbar,colormesh等)中的单元格大小,或者强制将其强制为某个值?

figure_width为常数(20英寸)和figure_height = cell_size * row_countcell_size为0.2英寸)时的代码,生成最后一张热图(单元格高度为5),单元格大小与其他单元格不同:

from matplotlib.backends.backend_pdf import PdfPages
import seaborn
import numpy as np

with PdfPages('test.pdf') as pdf_pages:
    column_count = 150
    for row_count in [100, 30, 10, 5]:
        data = np.random.rand(row_count, column_count)
        fig = plt.figure(figsize=(20, 0.2 * row_count))
        seaborn.heatmap(data, square=True, xticklabels=range(column_count),
                             yticklabels=range(row_count), cbar=None)
        plt.tight_layout()
        pdf_pages.savefig(fig)

我的代码figure_width = cell_size * column_countfigure_height = cell_size * row_countcell_size为0.2in),生成具有不同单元格大小的所有热图:

with PdfPages('test.pdf') as pdf_pages:
    column_count = 150
    for row_count in [100, 30, 10, 5]:
        data = np.random.rand(row_count, column_count)
        fig = plt.figure(figsize=(0.2 * column_count, 0.2 * row_count))
        seaborn.heatmap(data, square=True, xticklabels=range(column_count),
                             yticklabels=range(row_count), cbar=None)
        plt.tight_layout()
        pdf_pages.savefig(fig)

理想情况下,解决方案应该是column_count的参数化,因为它在一个PDF文档中保持不变,而在整个运行过程中都会发生变化。

1 个答案:

答案 0 :(得分:2)

您需要计算一些参数才能获得所需的结果 您可以从图形宽度开始。然后在热图周围定义一些边距和行数(应该是常量) 从这些数字中,您可以计算一次单元格(像素)的英寸大小 然后,对于每个图,您可以计算托管一定数量单元格所需的图形高度。这是在循环内完成的。此外,每个数字都需要设置相对边距(从绝对值计算)。

最后这会给出(忽略pdfpages,这似乎与此无关):

import matplotlib.pyplot as plt
import seaborn
import numpy as np

####  Free input parameters ####
cols = [100, 30, 10, 5]
# start by specifying figure width and margins
figwidth= 20. #inch
marg_top = 0.7
marg_bottom = 0.7
marg_left = 0.7
marg_right = 0.7

# number of cells along width
cells_in_row = 150

####  Automatic calculation ####
# determine cell size in inch
cellsize = (figwidth-marg_left-marg_right)/float(cells_in_row)
# now loop over cols:
for cells_in_column in cols:
    # calculate figure height in inches
    figheight = cellsize*cells_in_column+marg_top+marg_bottom
    # set figure size
    fig = plt.figure(figsize=(figwidth, figheight))
    # adjust margins (relative numbers) according to absolute values
    fig.subplots_adjust(bottom =marg_bottom/figheight ,top=1.-marg_top/figheight,
                        left=marg_left/figwidth, right=1.-marg_right/figwidth)

    data = np.random.rand(cells_in_column, cells_in_row)
    seaborn.heatmap(data, square=True, xticklabels=range(cells_in_row),
                         yticklabels=range(cells_in_column), cbar=None)
    fig.savefig("fig{}.png".format(cells_in_column))

当然,您也可以从给定的cellsize开始,然后根据它计算图形宽度:

# start by specifying cell size and margins
cellsize = 0.08 #inch
marg_top = 0.7
marg_bottom = 0.7
marg_left = 0.7
marg_right = 0.7

# number of cells along width
cells_in_row = 150
# determine figure width
figwidth = cellsize* cells_in_row + marg_left+marg_right