matplotlib 海运群集Map固定单元大小

uemypmqf  于 2023-01-09  发布在  其他
关注(0)|答案(2)|浏览(105)

我正在使用seaborn clustermap函数,我希望绘制多个单元格大小完全相同的图。轴标签的大小也应该相同。这意味着图形大小和纵横比需要更改,其余部分需要保持不变。

import pandas 
import seaborn
import numpy as np
dataFrameA = pd.DataFrame([ [1,2],[3,4] ])
dataFrameB = pd.DataFrame( np.arange(3*6).reshape(3,-1))

然后决定集群Map本身需要多大,大致如下:

dpi = 72
cellSizePixels = 150

这决定了dataFrameA应该是300 x 300像素。我认为这些需要转换为图形的大小单位,即cellSizePixels/dpi单位每像素。因此,对于dataFrameA,热图大小将是~2.01英寸。这里我引入一个问题:热图周围有一些东西,也会占用一些空间,我不知道这些东西到底会占用多少空间。
我试着用上面的公式来参数化热图函数,并猜测图像的大小:

def fixedWidthClusterMap( dpi, cellSizePixels, dataFrame):
    clustermapParams = {
        'square':False # Tried to set this to True before. Don't: the dendograms do not scale well with it.
    }
    figureWidth = (cellSizePixels/dpi)*dataFrame.shape[1]
    figureHeight= (cellSizePixels/dpi)*dataFrame.shape[0]
    return sns.clustermap( dataFrame, figsize=(figureWidth,figureHeight), **clustermapParams)

fixedWidthClusterMap(dpi, cellSizePixels, dataFrameA)
plt.show()
fixedWidthClusterMap(dpi, cellSizePixels, dataFrameB)
plt.show()

这产生:

我的问题:我怎样才能得到我想要的正方形单元格?

lf5gs5x2

lf5gs5x21#

这有点棘手,因为有相当多的事情要考虑,最后,这取决于你需要的尺寸有多“精确”。
看一下clustermap的代码,热图部分的设计与树图中使用的轴的比率为0.8。但我们还需要考虑放置轴的边距。如果知道热图轴的大小,就应该能够计算出生成正确形状所需的图形大小。

dpi = matplotlib.rcParams['figure.dpi']
marginWidth = matplotlib.rcParams['figure.subplot.right']-matplotlib.rcParams['figure.subplot.left']
marginHeight = matplotlib.rcParams['figure.subplot.top']-matplotlib.rcParams['figure.subplot.bottom']
Ny,Nx = dataFrame.shape
figWidth = (Nx*cellSizePixels/dpi)/0.8/marginWidth
figHeigh = (Ny*cellSizePixels/dpi)/0.8/marginHeight

不幸的是,matplotlib似乎必须在绘图过程中进行一些调整,因为这还不足以获得完全正方形的热图单元格,所以我选择在事后调整clustermap创建的各个轴的大小,从热图开始,然后是树状图轴。
我认为生成的图像非常接近您想要得到的结果,但我的测试有时会显示1-2像素的错误,我将其归因于舍入错误,因为所有大小之间的转换英寸和像素。

dataFrameA = pd.DataFrame([ [1,2],[3,4] ])
dataFrameB = pd.DataFrame( np.arange(3*6).reshape(3,-1))

def fixedWidthClusterMap(dataFrame, cellSizePixels=50):
    # Calulate the figure size, this gets us close, but not quite to the right place
    dpi = matplotlib.rcParams['figure.dpi']
    marginWidth = matplotlib.rcParams['figure.subplot.right']-matplotlib.rcParams['figure.subplot.left']
    marginHeight = matplotlib.rcParams['figure.subplot.top']-matplotlib.rcParams['figure.subplot.bottom']
    Ny,Nx = dataFrame.shape
    figWidth = (Nx*cellSizePixels/dpi)/0.8/marginWidth
    figHeigh = (Ny*cellSizePixels/dpi)/0.8/marginHeight

    # do the actual plot
    grid = sns.clustermap(dataFrame, figsize=(figWidth, figHeigh))

    # calculate the size of the heatmap axes
    axWidth = (Nx*cellSizePixels)/(figWidth*dpi)
    axHeight = (Ny*cellSizePixels)/(figHeigh*dpi)

    # resize heatmap
    ax_heatmap_orig_pos = grid.ax_heatmap.get_position()
    grid.ax_heatmap.set_position([ax_heatmap_orig_pos.x0, ax_heatmap_orig_pos.y0, 
                                  axWidth, axHeight])

    # resize dendrograms to match
    ax_row_orig_pos = grid.ax_row_dendrogram.get_position()
    grid.ax_row_dendrogram.set_position([ax_row_orig_pos.x0, ax_row_orig_pos.y0, 
                                         ax_row_orig_pos.width, axHeight])
    ax_col_orig_pos = grid.ax_col_dendrogram.get_position()
    grid.ax_col_dendrogram.set_position([ax_col_orig_pos.x0, ax_heatmap_orig_pos.y0+axHeight,
                                         axWidth, ax_col_orig_pos.height])
    return grid # return ClusterGrid object

grid = fixedWidthClusterMap(dataFrameA, cellSizePixels=75)
plt.show()
grid = fixedWidthClusterMap(dataFrameB, cellSizePixels=75)
plt.show()

第一节第一节第一节第一节第一次

t2a7ltrp

t2a7ltrp2#

不是一个完整的答案(不处理像素),但我怀疑OP已经在4年后继续前进。

def reshape_clustermap(cmap, cell_width=0.02, cell_height=0.02):
    ny, nx = cmap.data2d.shape

    hmap_width = nx * cell_width
    hmap_height = ny * cell_height

    hmap_orig_pos = cmap.ax_heatmap.get_position()
    cmap.ax_heatmap.set_position(
        [hmap_orig_pos.x0, hmap_orig_pos.y0, hmap_width, hmap_height]
    )

    top_dg_pos = cmap.ax_col_dendrogram.get_position()
    cmap.ax_col_dendrogram.set_position(
        [hmap_orig_pos.x0, hmap_orig_pos.y0 + hmap_height, hmap_width, top_dg_pos.height]
    )

    left_dg_pos = cmap.ax_row_dendrogram.get_position()
    cmap.ax_row_dendrogram.set_position(
        [left_dg_pos.x0, left_dg_pos.y0, left_dg_pos.width, hmap_height]
    )
    
    if cmap.ax_cbar:
        cbar_pos = cmap.ax_cbar.get_position()
        hmap_pos = cmap.ax_heatmap.get_position()
        cmap.ax_cbar.set_position(
            [cbar_pos.x0, hmap_pos.y1, cbar_pos.width, cbar_pos.height]
        )

cmap = sns.clustermap(dataFrameA)
reshape_clustermap(cmap)

相关问题