我写这篇文章是为了在用散点图绘制圆时提供参考帖子,但用户希望为散点圆提供真实的半径而不是抽象的尺寸。
我一直在四处寻找,还有其他帖子解释了它的理论,但还没有遇到现成的功能。我已经尝试过自己,希望我很快就能找到解决方案。
这是我到目前为止所拥有的:
import matplotlib.pyplot as plt
import numpy as np
def true_scatter(x, y, r, ax, **kwargs):
# Should work for an equal aspect axis
ax.set_aspect('equal')
# Access the DPI and figure size
dpi = ax.figure.dpi
fig_width_inch, _ = ax.figure.get_size_inches()
# Calculate plot size in data units
xlim = ax.get_xlim()
plot_width_data_units = xlim[1] - xlim[0]
# Calculate the scale factor: pixels per data unit
plot_width_pixels = fig_width_inch * dpi
scale = plot_width_pixels / plot_width_data_units
# Convert radius to pixels, then area to points squared
radius_pixels = r * scale
area_pixels_squared = np.pi * (radius_pixels ** 2)
area_points_squared = area_pixels_squared * (72 / dpi) ** 2
# Scatter plot with converted area
scatter = ax.scatter(x, y, s=area_points_squared, **kwargs)
return scatter
# Example with single scatter
fig, ax = plt.subplots()
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
scatter = true_scatter(0, 0, 1, ax)
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
plt.grid()
plt.show()
不幸的是,这并不是答案。我得到一个半径约为 1.55 而不是 1 的圆。 有人能发现我的方法有什么问题吗?
谢谢!
使用这个答案,我能够更新您的功能以正常工作。请注意以下更改:
pi/2*r^2
(你忘了 1/2)。import matplotlib.pyplot as plt
import numpy as np
plt.close("all")
def true_scatter(x, y, r, ax, **kwargs):
# Should work for an equal aspect axis
ax.set_aspect("equal")
fig = ax.figure
fig.canvas.draw() # need to draw before getting the dimensions
# Access the DPI and axes size
dpi = fig.dpi
ax_width = ax.get_window_extent().width
# Calculate plot size in data units
xlim = ax.get_xlim()
plot_width_data_units = xlim[1] - xlim[0] + 1 # +1 for some reason...
# Calculate the scale factor: pixels per data unit
# 72/dpi because that is the conversion factor from matplotlib
scale = ax_width/plot_width_data_units*(72/dpi)
# Convert radius to pixels, then area to points squared
radius_pixels = r*scale
s = 0.5*np.pi*radius_pixels**2
# the edge color makes the point look slightly larger than it is
kwargs["edgecolor"] = kwargs.get("edgecolor", "none")
# Scatter plot with converted area
scatter = ax.scatter(x, y, s=s, **kwargs)
return scatter
# Example with single scatter
fig, ax = plt.subplots()
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
scatter = true_scatter(0, 0, 1, ax)
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
plt.grid()
plt.show()
正如链接答案中提到的,调整图形大小或放大会破坏缩放比例。