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

时间:2019-04-09 08:19:14

标签: python arrays numpy

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

points = np.array([[x1, y1],
                   [x2, y2],
                   [x3, y3]])

我想计算一个后续数组,即从一个代理到其他代理的相对位置,而不是它本身。因此,使用以上数据,我想使用数组relative_positions生成数组pointspoints可以担任N个职位(我一次最多可以拥有50-100个业务代表)。

因此,使用上述points,我想产生输出:

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]]

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

agent_points = np.array([[10, 1],
                         [30, 3],
                         [25, 10],
                         [5, 5]])

我想生成输出:

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个案例(因为这是从代理到其自身的相对位置),但是我认为这不是“纯粹的”方法,因为我可能会意外删除恰好恰好在同一点(或非常接近)的特工

2 个答案:

答案 0 :(得分:1)

方法1

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

d = (a-a[:,None,:])
valid_mask = ~np.eye(len(a),dtype=bool)
out = d[valid_mask]

基本上,我们将a扩展到3D,使第一个轴成为outer-broadcastable,然后对其2D版本进行减法运算,得到{{1} }整形的输出,其中mxmx2m。示意性地放在-

a.shape[0]

More info

创建a[:, None, :] : 4 x 1 x 2 a : 4 x 2 output : 4 x 4 x 2 的另一种方法是-

valid_mask

方法2

我们将利用r = np.arange(len(a)) valid_mask = r[:,None] != r 获得np.lib.stride_tricks.as_strided数组(沿前两个轴)的非对角线遮罩,因此我们将在此处使用它来遮盖差异数组3D。此掩码的生成受here发布的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))

展示方法#2在方法#1的基础上改进的时间

d = (a-a[:,None,:])
out = nodiag_view3D(d).reshape(-1,a.shape[1])

答案 1 :(得分:0)

虽然我没有numpy专用解决方案(我确定它存在),但是双重for循环和id检查可以解决问题。不过,points的增长还需要一些时间。

points = [
    [x1, y1],
    [x2, y2],
    [x3, y3]
]

relative_positions = []
for point1 in points:
    for point2 in point:
        if id(point1) != id(point2):
            relative_positions.append([CALC_HERE_OR_FUNCTION])