【问题标题】:numpy create nxn array of nx2 dot product of nxnx2 arraynumpy 创建 nxn 数组的 nx2 点积 nxnx2 数组
【发布时间】:2017-11-23 03:05:48
【问题描述】:

我的目标是在模拟中为所有粒子创建一个粒子与每个其他粒子之间的角度的 nxn 数组。然后掩膜阵列可以选择特定视野中的所有粒子。

我的问题是如何逐行获取两个 nxn 数组(dx/距离和 dy/距离),然后将点积与一行 nx2 向量相乘,从而得到一个粒子与其他粒子之间的 nx1 角度数组粒子。对所有行重复此操作,并生成所有角度的 nxn 数组。

上下文 - 有 n 个位置 (x, y) 和速度 (x, y) 的粒子。每个粒子之间的偏移矢量可以通过创建一个 n x n 数组 dx 和 n x n 数组 dy 来计算。偏移向量(从粒子 i 到粒子 j)是 (xi - xj, yi - yj),我们可以从 (dx, dy) 得到。创建单位向量分量 dx/distance 和 dy/distance。

n = 4
k = 10
width = 50
boid_radius = 8
dim = 2

position = np.random.rand(n, dim) * width  # random dataset
velocity = 0.5 * np.random.random_sample((n, dim)) + 1

from sklearn import preprocessing as pp
velocity_normalized = pp.normalize(velocity)

dx = np.subtract.outer(position[:, 0], position[:, 0])
dy = np.subtract.outer(position[:, 1], position[:, 1])
distance = np.hypot(dx, dy)
# mask zeros
ox = dx/distance
ox = dy/distance

示例数据:

position
Out[233]: 
array([[  6.68625116,  34.35642605],
       [ 18.96766714,  45.61291941],
       [ 49.49921981,  37.95450382],
       [ 28.22272906,  42.90652135]])

dx
Out[234]: 
array([[  0.        , -12.28141597, -42.81296865, -21.5364779 ],
       [ 12.28141597,   0.        , -30.53155268,  -9.25506192],
       [ 42.81296865,  30.53155268,   0.        ,  21.27649075],
       [ 21.5364779 ,   9.25506192, -21.27649075,   0.        ]])

dy
Out[235]: 
array([[  0.        , -11.25649336,  -3.59807777,  -8.5500953 ],
       [ 11.25649336,   0.        ,   7.65841559,   2.70639806],
       [  3.59807777,  -7.65841559,   0.        ,  -4.95201753],
       [  8.5500953 ,  -2.70639806,   4.95201753,   0.        ]])

形成偏移单位向量分量:

distance = np.hypot(dx, dy).round()
array([[  0.,  17.,  43.,  23.],
       [ 17.,   0.,  31.,  10.],
       [ 43.,  31.,   0.,  22.],
       [ 23.,  10.,  22.,   0.]])

zeros = ma.masked_where(distance==0, distance)
masked_array(data =
 [[-- 17.0 43.0 23.0]
 [17.0 -- 31.0 10.0]
 [43.0 31.0 -- 22.0]
 [23.0 10.0 22.0 --]],
             mask =
 [[ True False False False]
 [False  True False False]
 [False False  True False]
 [False False False  True]],
       fill_value = 1e+20)

ox = dx / zeros
masked_array(data =
 [[-- -0.7224362336046727 -0.9956504337130146 -0.9363686041759272]
 [0.7224362336046727 -- -0.9848887960767806 -0.9255061924766889]
 [0.9956504337130146 0.9848887960767806 -- 0.9671132160733322]
 [0.9363686041759272 0.9255061924766889 -0.9671132160733322 --]],
             mask =
 [[ True False False False]
 [False  True False False]
 [False False  True False]
 [False False False  True]],
       fill_value = 1e+20)

下一步是在单位速度向量和单位偏移向量之间进行点积。这就是我卡住的地方。

velocity
Out[239]: 
array([[ 1.08980931,  1.10142992],
       [ 1.42378512,  1.31445528],
       [ 1.4599431 ,  1.34567875],
       [ 1.45934809,  1.03997269]])

pp.normalize(velocity)
Out[242]: 
array([[ 0.70334695,  0.71084672],
       [ 0.73475404,  0.67833363],
       [ 0.73529551,  0.67774665],
       [ 0.81437139,  0.58034407]])

下一步?我不知道如何对向量进行索引,以使 numpy 看起来像魔术一样完成所有工作。

【问题讨论】:

  • 问题是什么?
  • 我不会为此使用 sklearn 的标准化功能。如果我理解正确,您只需要dx/distancedy/distance 即可获得单位方向。
  • 好点,谢谢。不过,我的问题是将其转换为 numpythonic 方法,其中向量被视为一个整体,而不是使用 for 循环来遍历它们。
  • 什么for循环? dx/distance 例如在 Python 中计算所有标准化的 x 方向,而无需任何循环。
  • 谢谢,是的,我已经完成了这一步。它计算速度向量和每个粒子与其他所有粒子之间的偏移向量的点积,从而得到所有粒子与所有其他粒子之间的 nxn 角度数组。

标签: python numpy multidimensional-array vector masked-array


【解决方案1】:

感谢@kazemakase,回答时盯着我的脸……试图寻找过于复杂的东西。

import numpy as np
import sklearn.preprocessing as pp
import numpy.ma as ma

n = 4 # number of particles
dim = 2 # x and y coords

pos = np.random.randint(0,9,(n,2))
vel = np.random.randint(0,9,(n,2))
vel_unit = pp.normalize(vel)

dx = np.subtract.outer(pos[:,0], pos[:,0])
dy = np.subtract.outer(pos[:,1], pos[:,1])
distance = np.hypot(dx, dy).round()
m = ma.masked_where(distance==0, distance)
o_unit_x = dx/m
o_unit_y = dy/m
angles = o_unit_y * vel_unit[:,1] + o_unit_x * vel_unit[:,0]

只需要测试它是正确的,它正在做我认为的事情。

样本输出:

pos
Out[154]: 
array([[6, 1],
       [5, 7],
       [0, 7],
       [5, 2]])

vel
Out[155]: 
array([[6, 3],
       [7, 5],
       [5, 4],
       [2, 2]])

distance
Out[156]: 
array([[ 0.,  6.,  8.,  1.],
       [ 6.,  0.,  5.,  5.],
       [ 8.,  5.,  0.,  7.],
       [ 1.,  5.,  7.,  0.]])

angles.round(3)
Out[158]: 
masked_array(data =
 [[-- -0.446 0.117 0.0]
 [0.298 -- 0.781 0.707]
 [-0.335 -0.814 -- 0.0]
 [-0.447 -0.581 0.112 --]],
             mask =
 [[ True False False False]
 [False  True False False]
 [False False  True False]
 [False False False  True]],
       fill_value = 1e+20)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多