Python 如何计算点列表中从一个点到另一个点的相对向量

Python 如何计算点列表中从一个点到另一个点的相对向量,python,arrays,numpy,Python,Arrays,Numpy,我有一个(x,y)对中的点列表,它表示代理列表的位置。例如,给定3个代理,有3对点,我存储如下: points = np.array([[x1, y1], [x2, y2], [x3, y3]]) 我想计算一个后续数组,即从一个代理到每个其他代理的相对位置,但不是它本身。因此,使用上面的数据,我想使用数组点生成数组相对位置点可以有N位置(我可以在任何时候拥有50-100个以上的代理) 因此,使用上面描述的点,我想生成输

我有一个
(x,y)
对中的点列表,它表示代理列表的位置。例如,给定3个代理,有3对点,我存储如下:

points = np.array([[x1, y1],
                   [x2, y2],
                   [x3, y3]])
我想计算一个后续数组,即从一个代理到每个其他代理的相对位置,但不是它本身。因此,使用上面的数据,我想使用数组
生成数组
相对位置
<代码>点可以有
N
位置(我可以在任何时候拥有50-100个以上的代理)

因此,使用上面描述的
,我想生成输出:

relative_positions = [[x2-x1, y2-y1],
                      [x3-x1, y3-y1],
                      [x1-x2, y1-y2],
                      [x3-x2, y3-y2],
                      [x1-x3, y1-y3],
                      [x2-x3, y2-y3]]
relative_positions = [[30-10,  3-1],
                      [25-10, 10-1],
                      [5-10,   5-1],
                      [10-30,  1-3],
                      [25-30, 10-3],
                      [5-30,   5-3],
                      [10-25, 1-10],
                      [30-25, 3-10],
                      [5-25,  5-10],
                      [10-5,   1-5],
                      [30-5,   3-5],
                      [25-5,  10-5]]

例如,给定存储为numpy数组的四个代理位置:

agent_points = np.array([[10, 1],
                         [30, 3],
                         [25, 10],
                         [5, 5]])
我想生成输出:

relative_positions = [[x2-x1, y2-y1],
                      [x3-x1, y3-y1],
                      [x1-x2, y1-y2],
                      [x3-x2, y3-y2],
                      [x1-x3, y1-y3],
                      [x2-x3, y2-y3]]
relative_positions = [[30-10,  3-1],
                      [25-10, 10-1],
                      [5-10,   5-1],
                      [10-30,  1-3],
                      [25-30, 10-3],
                      [5-30,   5-3],
                      [10-25, 1-10],
                      [30-25, 3-10],
                      [5-25,  5-10],
                      [10-5,   1-5],
                      [30-5,   3-5],
                      [25-5,  10-5]]


我如何有效地进行这项工作?我考虑过只计算每个可能的差异,并删除0个案例(当它是代理到自身的相对位置时),但我不认为这是一种“纯粹”的方法,因为我可能会意外删除恰好位于同一点(或非常接近)的代理

虽然我没有特定于numpy的解决方案(我确信它存在),但双for循环和id检查可以很好地解决这个问题。但是,如果
点数增加,则需要一些时间

点=[
[x1,y1],
[x2,y2],
[x3,y3]
]
相对位置=[]
对于点中的点1:
对于点2中的点:
如果id(第1点)!=id(第2点):
相对位置。追加([CALC\u此处\u或\u函数])
方法#1

使用
a
输入数组,您可以-

d = (a-a[:,None,:])
valid_mask = ~np.eye(len(a),dtype=bool)
out = d[valid_mask]
基本上,我们将
a
扩展到
3D
,使得第一个轴可以
外部广播
,然后我们对其
2D
版本执行减法,从而产生
mxmx2
成形输出,
m
a.shape[0]
。示意性地放-

a[:, None, :]    :  4 x 1 x 2
a                :      4 x 2
output           :  4 x 4 x 2

另一种创建有效屏蔽的方法是-

r = np.arange(len(a))
valid_mask = r[:,None] != r
d = (a-a[:,None,:])
out = nodiag_view3D(d).reshape(-1,a.shape[1])
方法#2

我们将利用
np.lib.stride\u技巧.as\u stride
3D
数组(沿前两个轴)获得一个非对角掩码,以便在这里使用它来掩盖数组
d
的差异。此蒙版生成的灵感来自于发布的
2D
阵列问题,对于
3D
案例,其外观如下所示-

def nodiag_view3D(a):
    m = a.shape[0]
    p,q,r = a.strides
    return np.lib.stride_tricks.as_strided(a[:,1:], shape=(m-1,m,2), strides=(p+q,q,r))
要解决我们的问题,它将是-

r = np.arange(len(a))
valid_mask = r[:,None] != r
d = (a-a[:,None,:])
out = nodiag_view3D(d).reshape(-1,a.shape[1])

展示方法2如何改进方法1的时间安排
谢谢,我已经考虑过这个选项,但是我可能正在寻找numpy特定的解决方案,因为我关心速度(这个计算可以在每幕100k-10M次之间执行)。这是一个非常优雅的解决方案。我了解大部分正在发生的事情,你能解释一下
a[:,None,:]
在这种情况下会发生什么?@Athena添加了一些评论。