2014-11-04 2 views
0

У меня есть код для соответствия углам к квадрантам круга, в который они попадают. В настоящее время он дает мне результаты, которые я хочу, но я пытаюсь потерять цикл for, чтобы в полной мере использовать скорость numpy.Numpy vectorized меньше/больше, чем сравнение

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 является сравнение >/<. Если угол между lower_bounds[0] и upper_bounds[0], соответствующей записью из quadrant получает назначение 0, а так же для квадрантов 1, 2, 3. Есть ли способ сравнить массив углов для всех записей lower_bound и/или upper_bound одновременно?

(Если этот код кажется усложненной, некоторые это потому, что spawn_angles/квадрант центры не всегда [0, 90, 180, 270], они также могут быть, например, [45, 135, 225, 315])

ответ

1

Вы должны поднять все до одного размера. Вам нужен 2D-массив с каждым углом в виде строки и каждым segment_num в качестве столбца. (Или, может быть, вы хотите, транспонирование, но если это так, то вы должны быть в состоянии понять, что отсюда.)

Если вы просто делаете a > b где a и b оба 1D массивы, вы просите за 1- to-1.

Но если 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

1

Благодарим вас за понимание. Мой переработанный векторизованный код:

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

Для дальнейшего использования вы можете переписать angle_2d = angle.reshape ((len (angle), 1)) to angle_2d = angle.reshape ((- 1, 1)) –

Смежные вопросы