Matplotlib true_scatter函数问题:散点圆实际半径与预期不符
问题排查与修正:Matplotlib真实半径散点图
问题根源
你的true_scatter函数计算像素-数据单位比例时,错误使用了整个figure的宽度,而非绘图轴(ax)的实际显示宽度。figure包含边距、刻度标签等元素,轴的实际宽度远小于figure宽度,导致计算出的缩放比例偏大,最终生成的圆形面积(对应scatter的s参数)比预期大,视觉上半径约为1.55而非1。
另外,示例代码中调用函数后重复设置xlim和ylim的操作冗余,虽当前设置范围一致,但可能在其他场景下破坏等比例轴的布局。
修正后的代码
import matplotlib.pyplot as plt import numpy as np def true_scatter(x, y, r, ax, **kwargs): # 确保轴为等比例 ax.set_aspect('equal') # 获取轴的实际显示参数 dpi = ax.figure.dpi # 获取轴的实际宽度(像素)和数据范围 ax_width_pixels = ax.get_window_extent().width xlim = ax.get_xlim() plot_width_data_units = xlim[1] - xlim[0] # 计算像素/数据单位的缩放比例 scale = ax_width_pixels / plot_width_data_units # 将数据单位半径转换为平方点(scatter的s参数单位) radius_pixels = r * scale area_pixels = np.pi * (radius_pixels ** 2) # 1英寸=72点,1英寸=dpi像素 → 1像素=72/dpi点,面积转换为平方点 area_points = area_pixels * (72 / dpi) ** 2 # 绘制散点 scatter = ax.scatter(x, y, s=area_points, **kwargs) return scatter # 测试示例 fig, ax = plt.subplots() # 先设置轴范围,再调用函数 ax.set_xlim(-2, 2) ax.set_ylim(-2, 2) scatter = true_scatter(0, 0, 1, ax, facecolor='none', edgecolor='red') # 添加参考线验证半径 ax.axvline(x=1, color='gray', linestyle='--') ax.axhline(y=1, color='gray', linestyle='--') plt.grid() plt.show()
关键修改点
- 使用轴的实际宽度:通过
ax.get_window_extent().width获取轴的真实显示宽度(像素),替代原代码中整个figure的宽度,确保缩放比例计算准确。 - 移除冗余的轴范围设置:只在调用函数前设置一次
xlim和ylim,避免破坏等比例轴的布局。 - 添加参考线:测试代码中加入了x=1和y=1的虚线,可直观验证圆形半径是否符合预期。
验证方法
运行修正后的代码,红色空心圆的边缘会刚好对齐灰色参考线,说明半径准确为1个数据单位。
内容的提问来源于stack exchange,提问作者Yves ROBERT
相关产品推荐
相关产品推荐

