如何调整散点图的标记大小,使其与给定的半径相匹配? (使用 matplotlib 转换)
How to adjust the marker size of a scatter plot, so that it matches a given radius? (Using matplotlib transformations)
我想让散点图的标记与数据坐标中给定的半径相匹配。
我在 pyplot scatter plot marker size 中读到,标记大小以标记面积的形式给出,以点 ^2 为单位。
我尝试通过axes.transData
将给定的半径转换为点,然后通过pi * r^2
计算面积,但我没有成功。
可能是我转换错了。
也可能是 运行通过 VcXsrv 来自 WSL 的 matplotlib 导致了这个问题。
这是我想要完成的示例代码,结果作为代码下方的图像:
import matplotlib.pyplot as plt
from numpy import pi
n = 16
# create a n x n square with a marker at each point
x_data = []
y_data = []
for x in range(n):
for y in range(n):
x_data.append(x)
y_data.append(y)
fig,ax = plt.subplots(figsize=[7,7])
# important part:
# calculate the marker size so that the markers touch
# radius in data coordinates:
r = 0.5
# radius in display coordinates:
r_ = ax.transData.transform([r,0])[0] - ax.transData.transform([0,0])[0]
# marker size as the area of a circle
marker_size = pi * r_**2
ax.scatter(x_data, y_data, s=marker_size, edgecolors='black')
plt.show()
当我 运行 它与 s=r_
我得到的结果在左边,而与 s=marker_size
我得到的结果在下图的右边:
代码看起来非常好。如果您仅绘制 4 个点 (n=2
),就可以看到这一点:
半径(几乎)正好是您想要的 r=0.5
坐标单位。等等,差不多了?!
是的,问题是你在绘图之前确定坐标单位到图形点的大小,所以 before 设置限制,这会影响坐标单位而不是整体图形大小...
听起来很奇怪?也许。最重要的是,您使用默认轴限制 ((0,1)
x (0,1)
) 确定坐标变换,然后将它们放大到 (-0.75, 15.75)
x(-0.75, 15.75)
... 但是您没有减少标记大小。
所以要么在绘图之前将限制设置为已知大小:
ax.set_xlim((0,n-1))
ax.set_ylim((0,n-1))
完整代码为:
import matplotlib.pyplot as plt
from numpy import pi
n = 16
# create a n x n square with a marker at each point as dummy data
x_data = []
y_data = []
for x in range(n):
for y in range(n):
x_data.append(x)
y_data.append(y)
# open figure
fig,ax = plt.subplots(figsize=[7,7])
# set limits BEFORE plotting
ax.set_xlim((0,n-1))
ax.set_ylim((0,n-1))
# radius in data coordinates:
r = 0.5 # units
# radius in display coordinates:
r_ = ax.transData.transform([r,0])[0] - ax.transData.transform([0,0])[0] # points
# marker size as the area of a circle
marker_size = pi * r_**2
# plot
ax.scatter(x_data, y_data, s=marker_size, edgecolors='black')
plt.show()
...或根据新限制缩放标记的大小(您将需要了解它们或重新绘图)
# plot with invisible color
ax.scatter(x_data, y_data, s=marker_size, color=(0,0,0,0))
# calculate scaling
scl = ax.get_xlim()[1] - ax.get_xlim()[0]
# plot correctly (with color)
ax.scatter(x_data, y_data, s=marker_size/scl**2, edgecolors='blue',color='red')
这是一个相当乏味的想法,因为您需要绘制数据两次,但您保持轴的自动调整大小...
显然还有一些间距。这是对标记区域的误解。我们不是在谈论符号的面积(在这种情况下是一个圆圈),而是标记的边界框(想象一下,你想控制星星或星号的大小作为标记......人们永远不会计算符号的实际面积)。
所以计算面积不是pi * r_**2
而是正方形:(2*r_)**2
# open figure
fig,ax = plt.subplots(figsize=[7,7])
# setting the limits
ax.set_xlim((0,n-1))
ax.set_ylim((0,n-1))
# radius in data coordinates:
r = 0.5 # units
# radius in display coordinates:
r_ = ax.transData.transform([r,0])[0] - ax.transData.transform([0,0])[0] # points
# marker size as the area of a circle
marker_size = (2*r_)**2
# plot
ax.scatter(x_data, y_data, s=marker_size,linewidths=1)
#ax.plot(x_data, y_data, "o",markersize=2*r_)
plt.show()
只要您添加一条边(标记周围的非零边界),它们就会重叠:
如果您使用 plot
(如果所有标记的大小都应与 docs 状态的“注释”相同,则速度会更快)。 markersize
只是标记的宽度(不是面积):
ax.plot(x_data, y_data, "o",markersize=2*r_,color='magenta')
我想让散点图的标记与数据坐标中给定的半径相匹配。
我在 pyplot scatter plot marker size 中读到,标记大小以标记面积的形式给出,以点 ^2 为单位。
我尝试通过axes.transData
将给定的半径转换为点,然后通过pi * r^2
计算面积,但我没有成功。
可能是我转换错了。 也可能是 运行通过 VcXsrv 来自 WSL 的 matplotlib 导致了这个问题。
这是我想要完成的示例代码,结果作为代码下方的图像:
import matplotlib.pyplot as plt
from numpy import pi
n = 16
# create a n x n square with a marker at each point
x_data = []
y_data = []
for x in range(n):
for y in range(n):
x_data.append(x)
y_data.append(y)
fig,ax = plt.subplots(figsize=[7,7])
# important part:
# calculate the marker size so that the markers touch
# radius in data coordinates:
r = 0.5
# radius in display coordinates:
r_ = ax.transData.transform([r,0])[0] - ax.transData.transform([0,0])[0]
# marker size as the area of a circle
marker_size = pi * r_**2
ax.scatter(x_data, y_data, s=marker_size, edgecolors='black')
plt.show()
当我 运行 它与 s=r_
我得到的结果在左边,而与 s=marker_size
我得到的结果在下图的右边:
代码看起来非常好。如果您仅绘制 4 个点 (n=2
),就可以看到这一点:
半径(几乎)正好是您想要的 r=0.5
坐标单位。等等,差不多了?!
是的,问题是你在绘图之前确定坐标单位到图形点的大小,所以 before 设置限制,这会影响坐标单位而不是整体图形大小...
听起来很奇怪?也许。最重要的是,您使用默认轴限制 ((0,1)
x (0,1)
) 确定坐标变换,然后将它们放大到 (-0.75, 15.75)
x(-0.75, 15.75)
... 但是您没有减少标记大小。
所以要么在绘图之前将限制设置为已知大小:
ax.set_xlim((0,n-1))
ax.set_ylim((0,n-1))
完整代码为:
import matplotlib.pyplot as plt
from numpy import pi
n = 16
# create a n x n square with a marker at each point as dummy data
x_data = []
y_data = []
for x in range(n):
for y in range(n):
x_data.append(x)
y_data.append(y)
# open figure
fig,ax = plt.subplots(figsize=[7,7])
# set limits BEFORE plotting
ax.set_xlim((0,n-1))
ax.set_ylim((0,n-1))
# radius in data coordinates:
r = 0.5 # units
# radius in display coordinates:
r_ = ax.transData.transform([r,0])[0] - ax.transData.transform([0,0])[0] # points
# marker size as the area of a circle
marker_size = pi * r_**2
# plot
ax.scatter(x_data, y_data, s=marker_size, edgecolors='black')
plt.show()
...或根据新限制缩放标记的大小(您将需要了解它们或重新绘图)
# plot with invisible color
ax.scatter(x_data, y_data, s=marker_size, color=(0,0,0,0))
# calculate scaling
scl = ax.get_xlim()[1] - ax.get_xlim()[0]
# plot correctly (with color)
ax.scatter(x_data, y_data, s=marker_size/scl**2, edgecolors='blue',color='red')
这是一个相当乏味的想法,因为您需要绘制数据两次,但您保持轴的自动调整大小...
显然还有一些间距。这是对标记区域的误解。我们不是在谈论符号的面积(在这种情况下是一个圆圈),而是标记的边界框(想象一下,你想控制星星或星号的大小作为标记......人们永远不会计算符号的实际面积)。
所以计算面积不是pi * r_**2
而是正方形:(2*r_)**2
# open figure
fig,ax = plt.subplots(figsize=[7,7])
# setting the limits
ax.set_xlim((0,n-1))
ax.set_ylim((0,n-1))
# radius in data coordinates:
r = 0.5 # units
# radius in display coordinates:
r_ = ax.transData.transform([r,0])[0] - ax.transData.transform([0,0])[0] # points
# marker size as the area of a circle
marker_size = (2*r_)**2
# plot
ax.scatter(x_data, y_data, s=marker_size,linewidths=1)
#ax.plot(x_data, y_data, "o",markersize=2*r_)
plt.show()
如果您使用 plot
(如果所有标记的大小都应与 docs 状态的“注释”相同,则速度会更快)。 markersize
只是标记的宽度(不是面积):
ax.plot(x_data, y_data, "o",markersize=2*r_,color='magenta')