Поиск ближайшего соседа: Питон
У меня есть двумерный массив:
MyArray = array([6588252.24, 1933573.3, 212.79, 0, 0],
[6588253.79, 1933602.89, 212.66, 0, 0],
etc...)
Первые два элемента MyArray[0]
а также MyArray[1]
являются координатами X и Y точек.
Для каждого элемента в массиве я хотел бы найти самый быстрый способ вернуть его единственного ближайшего соседа в радиусе X единиц. Мы предполагаем, что это в 2D-пространстве.
скажем для этого примера X = 6
,
Я решил проблему, сравнив каждый элемент с каждым другим, но это занимает 15 минут или около того, когда ваш список имеет длину 22 000 пунктов. Мы надеемся в конечном итоге запустить это в списках около 30 миллионов баллов.
Я читал о деревьях Kd и понимаю основную концепцию, но у меня были проблемы с пониманием того, как их написать.
2 ответа
Спасибо Джону Виньярду за предложение Скипи. После некоторого хорошего исследования и тестирования вот решение этого вопроса:
Предварительные условия: Установите Numpy и SciPy
Импортировать модули SciPy и Numpy
Сделайте копию 5-мерного массива, включающего только значения X и Y.
Создать экземпляр
cKDTree
в качестве таких:YourTreeName = scipy.spatial.cKDTree(YourArray, leafsize=100) #Play with the leafsize to get the fastest result for your dataset
Запрос
cKDTree
для ближайшего соседа в пределах 6 единиц как таковых:for item in YourArray: TheResult = YourTreeName.query(item, k=1, distance_upper_bound=6)
за каждый элемент в
YourArray
,TheResult
будет кортеж расстояния между двумя точками, и индекс местоположения точки вYourArray
,
Использовать
sklearn.neighbors
from sklearn.neighbors import NearestNeighbors
#----- Creating example data start -------
number_of_points = 10
x_vect = np.sin(range(number_of_points))
y_vect = np.cos(range(number_of_points))
coords_vect = np.vstack([x_vect, y_vect]).T
#----- Creating example data end -------
knn = NearestNeighbors(n_neighbors=3)
knn.fit(coords_vect)
distance_mat, neighbours_mat = knn.kneighbors(coords_vect)
Полученные результаты:
neighbours_mat = array([[0, 6, 7],
[1, 7, 8],
[2, 8, 9],
[3, 9, 4],
[4, 3, 5],
[5, 6, 4],
[6, 0, 5],
[7, 1, 0],
[8, 2, 1],
[9, 3, 2]], dtype=int64)
Обратите внимание, что первый столбец — это сам узел, второй столбец — ближайший сосед, третий столбец — второй ближайший сосед. Вы можете получить больше соседей, увеличив
n_neighbors
@
NearestNeighbors(n_neighbors=3)
инициализация.
distance_mat
являются расстояниями каждого узла от его соседей, обратите внимание, что каждый узел имеет расстояние 0 до себя, поэтому первый столбец всегда равен нулю:
distance_mat = array([[0. , 0.28224002, 0.70156646],
[0. , 0.28224002, 0.70156646],
[0. , 0.28224002, 0.70156646],
[0. , 0.28224002, 0.95885108],
[0. , 0.95885108, 0.95885108],
[0. , 0.95885108, 0.95885108],
[0. , 0.28224002, 0.95885108],
[0. , 0.28224002, 0.70156646],
[0. , 0.28224002, 0.70156646],
[0. , 0.28224002, 0.70156646]])
Нанесение точек:
plt.figure()
plt.scatter(x_vect, y_vect)
for x,y, label in zip (x_vect, y_vect, range(number_of_points)):
plt.text(x,y,label)