2017-02-02 8 views
2

Указанных два массива, где каждая строка представляет собой окружность (х, у, г):Векторизация операции между всеми парами элементов в двух Numpy массивов

data = {} 
data[1] = np.array([[455.108, 97.0478, 0.0122453333], 
        [403.775, 170.558, 0.0138770952], 
        [255.383, 363.815, 0.0179857619]]) 
data[2] = np.array([[455.103, 97.0473, 0.012041], 
        [210.19, 326.958, 0.0156912857], 
        [455.106, 97.049, 0.0150472381]]) 

Я хотел бы вытащить все из пар окружностей, которые не являются разрозненными. Это может быть сделано путем:

close_data = {} 
for row1 in data[1]: #loop over first array 
    for row2 in data[2]: #loop over second array 
     condition = ((abs(row1[0]-row2[0]) + abs(row1[1]-row2[1])) < (row1[2]+row2[2])) 
     if condition: #circles overlap if true 
      if tuple(row1) not in close_data.keys():       
       close_data[tuple(row1)] = [row1, row2] #pull out close data points 
      else: 
       close_data[tuple(row1)].append(row2) 

for k, v in close_data.iteritems(): 
    print k, v 
#desired outcome 
#(455.108, 97.047799999999995, 0.012245333299999999) 
#[array([ 4.55108000e+02, 9.70478000e+01, 1.22453333e-02]), 
# array([ 4.55103000e+02, 9.70473000e+01, 1.2040000e-02]), 
# array([ 4.55106000e+02, 9.70490000e+01, 1.50472381e-02])] 

Однако несколько петель над массивами очень неэффективны для больших наборов данных. Можно ли векторизовать вычисления, поэтому я получаю преимущество использования numpy?

ответ

3

Самый сложный бит - это фактически получение вашего представления информации. О, и я вставил несколько квадратов. Если вы действительно не хотите евклидовых дистанций, вам нужно вернуться обратно.

import numpy as np 

data = {} 
data[1] = np.array([[455.108, 97.0478, 0.0122453333], 
        [403.775, 170.558, 0.0138770952], 
        [255.383, 363.815, 0.0179857619]]) 
data[2] = np.array([[455.103, 97.0473, 0.012041], 
        [210.19, 326.958, 0.0156912857], 
        [455.106, 97.049, 0.0150472381]]) 

d1 = data[1][:, None, :] 
d2 = data[2][None, :, :] 
dists2 = ((d1[..., :2] - d2[..., :2])**2).sum(axis = -1) 
radss2 = (d1[..., 2] + d2[..., 2])**2 

inds1, inds2 = np.where(dists2 <= radss2) 

# translate to your representation: 

bnds = np.r_[np.searchsorted(inds1, np.arange(3)), len(inds1)] 
rows = [data[2][inds2[bnds[i]:bnds[i+1]]] for i in range(3)] 
out = dict([(tuple (data[1][i]), rows[i]) for i in range(3) if rows[i].size > 0]) 
+0

будет иметь вид в ближайшее время, спасибо! Я ни в коем случае не женат на финальном представлении, мне действительно нужен способ сопоставления всех связанных кругов в группах, и, как мне казалось, это естественный способ вытащить его из цикла. –

0

Вот чистый numpythonic путь (a является и b является data[2]):

In [80]: p = np.arange(3) # for creating the indices of combinations using np.tile and np.repeat 

In [81]: a = a[np.repeat(p, 3)] # creates the first column of combination array 

In [82]: b = b[np.tile(p, 3)] # creates the second column of combination array 

In [83]: abs(a[:, :2] - b[:, :2]).sum(1) < a[:, 2] + b[:, 2] 
Out[83]: array([ True, False, True, True, False, True, True, False, True], dtype=bool)