在 Matplotlib 中将散点图中的标记尺寸正确调整为半径 R

cal*_*ben 5 python matplotlib scatter-plot

我有一个限制为 -1 到 1 的图。我知道散点图不会以大小为半径来绘制,而是以大小为点来绘制。

我需要根据每个点的大小(我将其作为半径)正确缩放绘图。通过修改以下代码可以实现这一点吗?

fig, ax = plt.subplots(1)
ax.set_title("Post Synaptic Neurons")
sizes = [x.size * 100 for x in post_synaptic_neurons]
offsets = [(x.origin[0],x.origin[1]) for x in post_synaptic_neurons]
print(sizes)
ax.scatter([x.origin[0] for x in post_synaptic_neurons], [x.origin[1] for x in post_synaptic_neurons], 
  cmap=plt.cm.hsv, s=sizes, alpha=0.5)
ax.set_xlim([-1,1]) 
ax.set_ylim([-1,1])
ax.set_aspect(1)
plt.tight_layout
Run Code Online (Sandbox Code Playgroud)

如果没有,有人可以向我解释为什么 matplotlib 没有在绘图比例上绘制具有特定半径的圆的函数吗?我没想到这会成为一个问题,但我的困难背后一定有充分的理由。

Jor*_* He 6

是的,有一种方法可以在绘图比例上绘制具有特定半径的散点图。方法是仔细定义图形大小并以点数指定半径,因为文档说plt.scatter参数s是“以点**2为单位的标记大小”。

下面是在位置 [0.5, 0.5] 处绘制半径为 0.1 的圆的示例

import matplotlib.pyplot as plt
plt.figure(figsize=[5, 5])
ax = plt.axes([0.1, 0.1, 0.8, 0.8], xlim=(0, 1), ylim=(0, 1))
points_whole_ax = 5 * 0.8 * 72    # 1 point = dpi / 72 pixels
radius = 0.1
points_radius = 2 * radius / 1.0 * points_whole_ax
ax.scatter(0.5, 0.5, s=points_radius**2, color='r')
plt.grid()
plt.show()
Run Code Online (Sandbox Code Playgroud)

这里的关键是,matplotlib 中点的标准大小是每英寸 72 点 (ppi),无论 dpi 是多少。公式中的系数 2points_radius来自以下事实:该面积是位于该区域之外的盒子的面积,即area = (2 * radius)**2。输出图如下所示。

代码比例半径为 0.1 的圆,用 plt.scatter 绘制


jak*_*vdp 4

据我所知,没有一种高级方法可以做到这一点,但你可以让它与EllipseCollection. 由于您的数据不可用,我做了一些并编写了以下代码:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.collections import EllipseCollection

x, y = 1500 * np.random.rand(2, 100)
size = 50 + 10 * np.random.randn(100)
color = np.random.rand(100)
cmap = plt.cm.hsv

fig, ax = plt.subplots(1, 2, figsize=(16, 6),
                       sharex=True, sharey=True)
ax[0].scatter(x, y, s=size, c=color, cmap=cmap)

offsets = list(zip(x, y))
ax[1].add_collection(EllipseCollection(widths=size, heights=size, angles=0, units='xy',
                                       facecolors=plt.cm.hsv(color),
                                       offsets=offsets, transOffset=ax[1].transData))
ax[1].axis('equal') # set aspect ratio to equal
ax[1].axis([-400, 1800, -200, 1600])
Run Code Online (Sandbox Code Playgroud)

结果就是你所希望的;左边是简单的散点图,右边是缩放图: 在此输入图像描述

如果您缩放绘图,例如将轴限制更改为ax[1].axis([200, 1000, 300, 900]),则右侧绘图上的圆圈将根据需要缩放:

在此输入图像描述

您可以在matplotlib 文档中找到更多使用集合的示例。