Matplotlib如何实现矩阵图(matrixplot)的可变列宽?
自定义行列宽度的矩阵图解决方案
嘿,我完全懂你想要的效果——让矩阵的行列按照指定的宽度/高度展示,而非默认的等宽样式。其实用Matplotlib的imshow配合自定义坐标轴范围就能轻松实现,比matshow灵活得多,下面是具体的实现方案:
简便实现代码(推荐)
import matplotlib.pyplot as plt import numpy as np # 生成示例矩阵 samplemat = np.random.rand(3, 3) # 指定列宽度(行高度可同理自定义) widths = np.array([.7, .2, .1]) # 若需自定义行高度,取消下方注释 # heights = np.array([.3, .5, .2]) # 计算列宽度的累积和,用于定位每个列块的边界 cum_widths = np.concatenate([[0], np.cumsum(widths)]) # 行高度累积和(自定义行高时使用) # cum_heights = np.concatenate([[0], np.cumsum(heights)]) # 创建画布与轴对象 fig, ax = plt.subplots() # 用imshow绘制矩阵,通过extent指定坐标范围 # extent格式为[左边界, 右边界, 下边界, 上边界] im = ax.imshow(samplemat, extent=[cum_widths[0], cum_widths[-1], 0, len(samplemat)], aspect='auto') # 自动适配自定义宽高比例 # 设置x轴刻度到每个列块的中心位置,保证标签对齐 ax.set_xticks((cum_widths[:-1] + cum_widths[1:]) / 2) ax.set_xticklabels(range(1, len(widths)+1)) # 可替换为自定义标签 # 自定义行高度时,设置y轴刻度 # ax.set_yticks((cum_heights[:-1] + cum_heights[1:]) / 2) # ax.set_yticklabels(range(1, len(heights)+1)) # 可选:添加颜色条 fig.colorbar(im) plt.show()
关键逻辑解释
- 累积和计算:
cum_widths会生成每个列块的边界位置,比如示例中是[0, 0.7, 0.9, 1.0],对应第一列占0-0.7区间,第二列0.7-0.9,第三列0.9-1.0。 - extent参数:告诉
imshow图像的坐标范围,让每个矩阵元素精准对应到指定宽度的区间内。 - 刻度对齐:把x轴刻度放在列块中心,确保标签和对应块的位置匹配,视觉上更清晰。
- aspect='auto':避免Matplotlib强制等比例显示,让图像自动适配我们设置的宽高比例。
替代方案:手动绘制分块矩阵(带边框)
如果需要更精细的样式控制(比如给每个块加边框),可以用Rectangle逐个绘制矩阵元素:
import matplotlib.pyplot as plt import numpy as np samplemat = np.random.rand(3, 3) widths = np.array([.7, .2, .1]) heights = np.array([.3, .5, .2]) # 自定义行高度 cum_widths = np.concatenate([[0], np.cumsum(widths)]) cum_heights = np.concatenate([[0], np.cumsum(heights)]) fig, ax = plt.subplots() # 归一化矩阵值,适配颜色映射 norm = plt.Normalize(samplemat.min(), samplemat.max()) cmap = plt.get_cmap('viridis') # 逐个绘制带边框的矩形块 for i in range(samplemat.shape[0]): for j in range(samplemat.shape[1]): x_left = cum_widths[j] y_bottom = cum_heights[i] rect = plt.Rectangle( (x_left, y_bottom), widths[j], heights[i], color=cmap(norm(samplemat[i, j])), edgecolor='white' # 白色边框区分块 ) ax.add_patch(rect) # 设置坐标轴范围 ax.set_xlim(0, cum_widths[-1]) ax.set_ylim(0, cum_heights[-1]) ax.set_aspect('auto') # 添加颜色条 sm = plt.cm.ScalarMappable(norm=norm, cmap=cmap) sm.set_array([]) fig.colorbar(sm) plt.show()
这种方法能实现更接近分块矩阵的视觉效果,适合需要额外样式定制的场景。
内容的提问来源于stack exchange,提问作者Matías Iglesias
相关产品推荐
相关产品推荐

