Numpy 矢量化小于/大于比较

Numpy vectorized less than/greater than comparisons

提问人:Marius 提问时间:11/5/2014 更新时间:11/5/2014 访问量:2325

问:

我有一些代码可以匹配它们所属圆的象限的角度。它目前给了我想要的结果,但我试图失去 for 循环以充分利用 numpy 的速度。

import numpy as np

angle = np.array([350, 10, 80, 100, 170, 190, 260, 280])
# Center of each quadrant
spawn_angles = np.array([0, 90, 180, 270])

segment_degrees = np.diff(spawn_angles)[0]
lower_bounds = spawn_angles - (segment_degrees / 2)
upper_bounds = spawn_angles + (segment_degrees / 2)
max_upper = upper_bounds.max()
# Wrap angles larger than the upper bound of the last segment
# back to a negative angle
angle[angle > max_upper] -= 360
quadrant = np.zeros_like(angle, dtype=np.float64)
# Want to make sure that quadrants that don't get calculated
# properly get assigned an invalid number, i.e. -1
quadrant.fill(-1)
for segment_num in range(len(spawn_angles)):
    in_segment = ((angle > lower_bounds[segment_num]) & 
                  (angle < upper_bounds[segment_num]))
    quadrant[in_segment] = segment_num

# Expected/current output
quadrant
Out[16]: array([ 0.,  0.,  1.,  1.,  2.,  2.,  3.,  3.])

基本上,我无法弄清楚如何在 numpy 中做什么的部分是 / 比较。 如果角度介于 和 之间,则对应的条目 of 被分配为 0,同样,对于象限 1、2、3。有什么办法吗 将角度数组与 and/or 的所有条目同时进行比较?><lower_bounds[0]upper_bounds[0]quadrantlower_boundupper_bound

(如果此代码看起来过于复杂,部分原因是 /quadrant 居中 并非总是如此,它们也可以是例如spawn_angles[0, 90, 180, 270][45, 135, 225, 315])

python numpy

评论


答:

1赞 abarnert 11/5/2014 #1

你需要把所有东西都提升到一个维度。您需要一个 2D 数组,每个角度为一行,每个角度segment_num为一列。(或者,也许你想要转置,但如果是这样,你应该能够从这里弄清楚。

如果你只是做 where 和 都是 1D 数组,你就要求进行 1 对 1 的元素比较。a > bab

但是,如果是 2D 数组,则要求进行笛卡尔乘积比较。a

换言之:

>>> array.reshape((8,1)) > lower_bounds
array([[ True,  True,  True,  True],
       [ True, False, False, False],
       [ True,  True, False, False],
       [ True,  True, False, False],
       [ True,  True,  True, False],
       [ True,  True,  True, False],
       [ True,  True,  True,  True],
       [ True,  True,  True,  True]], dtype=bool)

你应该能够从那里弄清楚。

评论

0赞 Marius 11/5/2014
太好了,明白了,感谢您朝着正确的方向推动。我将很快发布我重新设计的代码作为解决方案,如果您发现任何明显的错误,请告诉我。
1赞 Marius 11/5/2014 #2

感谢 abarnert 在这里提供的关键见解。我重新设计的矢量化代码:

import numpy as np

angle = np.array([350, 10, 80, 100, 170, 190, 260, 280])
# Center of each quadrant
spawn_angles = np.array([0, 90, 180, 270])

segment_degrees = np.diff(spawn_angles)[0]
lower_bounds = spawn_angles - (segment_degrees / 2)
upper_bounds = spawn_angles + (segment_degrees / 2)
max_upper = upper_bounds.max()
# Wrap angles larger than the upper bound of the last segment
# back to a negative angle
angle[angle > max_upper] -= 360
angle_2d = angle.reshape((len(angle), 1))
cmp_array = ((angle_2d > lower_bounds) & 
             (angle_2d < upper_bounds))
quadrant = np.argwhere(cmp_array)[:, 1]
quadrant
Out[29]: array([0, 0, 1, 1, 2, 2, 3, 3], dtype=int64)

评论

0赞 Chris.Wilson 9/26/2017
仅供将来参考,您可以将 angle_2d = angle.reshape((len(angle), 1)) 重写为 angle_2d = angle.reshape((-1, 1))