2014-11-09 4 views
3

Я пытаюсь найти пары точек (x, y) на максимальном расстоянии друг от друга. Я подумал, что проще всего было бы создать DataFrame и пройти через каждую точку один за другим, вычисляя, есть ли точки с координатами (x, y) на расстоянии r от данной точки (x_0, y_0). Затем разделите общее количество обнаруженных пар на 2.Pandas: точки нахождения на максимальном расстоянии

%pylab inline 
import pandas as pd 

def find_nbrs(low, high, num, max_d): 
    x = random.uniform(low, high, num) 
    y = random.uniform(low, high, num) 
    points = pd.DataFrame({'x':x, 'y':y}) 

    tot_nbrs = 0 

    for i in arange(len(points)): 
     x_0 = points.x[i] 
     y_0 = points.y[i] 

     pt_nbrz = points[((x_0 - points.x)**2 + (y_0 - points.y)**2) < max_d**2] 
     tot_nbrs += len(pt_nbrz) 
     plot (pt_nbrz.x, pt_nbrz.y, 'r-') 

    plot (points.x, points.y, 'b.') 
    return tot_nbrs 

print find_nbrs(0, 1, 50, 0.1) 
  1. Прежде всего, это не всегда находить правильные пары (я вижу точки, которые находятся в пределах указанного расстояния, которые не меченые).

  2. Если я пишу plot(..., 'or'), он выделяет все точки. Это означает, что pt_nbrz = points[((x_0 - points.x)**2 + (y_0 - points.y)**2) < max_d**2] возвращает хотя бы один (x, y). Зачем? Должен ли он возвращать пустой массив, если сравнение False?

  3. Как я могу сделать все вышеизложенное более элегантно в Пандах? Например, без необходимости прокручивать каждый элемент.

+0

Поправьте меня, если я ошибаюсь, но вы делаете в O (N) поиск, когда я думаю, что вы want - поиск O (n^2). Вы в основном проверяете расстояние между x0: y0, x1: y1, x2: y2 ... когда то, что я думаю, вы хотите сделать, это проверить x0: y0, x0: y1, ... x1: y0, x1: y1, x1: y2 .... – Greg

+0

Но если я ошибаюсь в отношении того, что вы хотите, то это будет хорошо работать для вас http://stackoverflow.com/questions/1401712/how-can-the-euclidean-distance-be-calculated -with-numpy – Greg

+0

Спасибо за ссылку. У меня есть некоторые проблемы с выяснением того, как использовать numpy.linalg.norm для вычисления расстояния, несмотря на ответ. Какой формат должен содержать a и b в примере? Re: O (n^2), я думал, что это то, что я делал: то есть, проходя через каждый элемент dataframe и находить все остальные элементы, которые удовлетворяют сравнению. Это должно идентифицировать всех близнецов дважды, поэтому, чтобы получить число, я просто делю финальный счет на 2. –

ответ

7

Функциональность, которую вы ищете, входит в состав scipy's spatial distance module.

Вот пример того, как вы могли его использовать. Настоящая магия находится в squareform(pdist(points)).

from scipy.spatial.distance import pdist, squareform 
import numpy as np 
import matplotlib.pyplot as plt 

points = np.random.uniform(-.5, .5, (1000,2)) 

# Compute the distance between each different pair of points in X with pdist. 
# Then, just for ease of working, convert to a typical symmetric distance matrix 
# with squareform. 
dists = squareform(pdist(points)) 

poi = points[4] # point of interest 
dist_min = .1 
close_points = dists[4] < dist_min 

print("There are {} other points within a distance of {} from the point " 
    "({:.3f}, {:.3f})".format(close_points.sum() - 1, dist_min, *poi)) 

There are 27 other points within a distance of 0.1 from the point (0.194, 0.160)

Для целей визуализации:

f,ax = plt.subplots(subplot_kw= 
    dict(aspect='equal', xlim=(-.5, .5), ylim=(-.5, .5))) 
ax.plot(points[:,0], points[:,1], 'b+ ') 
ax.plot(poi[0], poi[1], ms=15, marker='s', mfc='none', mec='g') 
ax.plot(points[close_points,0], points[close_points,1], 
    marker='o', mfc='none', mec='r', ls='') # draw all points within distance 

t = np.linspace(0, 2*np.pi, 512) 
circle = dist_min*np.vstack([np.cos(t), np.sin(t)]).T 
ax.plot((circle+poi)[:,0], (circle+poi)[:,1], 'k:') # Add a visual check for that distance 
plt.show() 

enter image description here

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