python - Seaborn clustermap 固定单元大小
问题描述
我正在使用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))
然后决定集群图本身需要多大,大致如下:
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()
我的问题:我如何获得正是我想要的大小的方形单元格?
解决方案
这有点棘手,因为有很多事情需要考虑,最后,这取决于你需要的尺寸有多“精确”。
查看热图部分的代码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()
推荐阅读
- php - 为什么while循环创建/覆盖2个单独的数组
- r - 删除第二个重复行
- ios - UIScrollView 中的 UIView 中的 UITableView。滚动表格视图和滚动滚动视图时
- python-3.x - 为什么我的 Odoo 13 实例仅使用调试资产运行?
- python - 如何从 REST API 导入数据和包
- java - JAVA - 如何按对象元素对 ArrayList 进行排序?
- python - 如何调整多边形的大小以适合画布?Python Tkinter
- python - PYTHON Tensorflow,文本分析:文件中的非 ASCII 字符“\xc3”
- php - 使用php从网站链接中提取数字
- html - 在居中的图像/视频下直接对齐文本