Scipy KDTree() Получить соседние точки сетки прямоугольной формы

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

Но когда данные координаты очень близки к точке сетки, а сетка имеет более длинные шаги с одной стороны, это дает что-то вроде:

scipy.spatial.KDtree результаты

Итак, на этом изображении точкой для вычисления ближайшего соседа является красная точка, которую вы видите в левом нижнем углу. Результаты, данные KDTree, представляют собой синие квадраты. Зеленый ромб — это четвертая точка, которую я хотел бы получить вместо одинокого синего в верхней части изображения.

Код :

>>> grid.head()
          x         y
0  0.000000 -9.490125
1  0.959131 -9.490125
2  1.918263 -9.490125
3  2.877394 -9.490125
4  3.836526 -9.490125

>>> pt
[4.0092010999999998e-05, -9.4901299629261011]

>>>tree = ssp.KDTree(grid)
>>>dis, idx = tree.query(pt,4)

>>> idx 
array([  0,  71,   1, 142])

>>> grid.iloc[idx]
            x         y
0    0.000000 -9.490125
71   0.000000 -8.980481
1    0.959131 -9.490125
142  0.000000 -8.470837

Вопрос:

Есть ли способ указать, что нам нужен массив прямоугольной формы в запросе или что-то в этом роде? Может быть, указав, что нам нужны только 2 y ​​для одного x?


person Alex    schedule 04.05.2017    source источник


Ответы (1)


Во-первых, давайте попробуем создать минимальный, полный и проверяемый пример

>>> import pandas as pd
>>> import numpy as np
>>> x0, dx = 0, 0.959131
>>> x  = np.arange(x0, x0+5*dx,dx) 
>>> y0, dy = -9.4901299629261011, 8.980481-8.470837
>>> y  = np.arange(y0, y0+2*dy,dy)
>>> data = np.transpose([np.tile(x, len(y)), np.repeat(y, len(x))])
>>> grid = pd.DataFrame(data=data, columns=['x', 'y'])
>>> grid.head()
          x        y
0  0.000000 -9.49013
1  0.959131 -9.49013
2  1.918262 -9.49013
3  2.877393 -9.49013
4  3.836524 -9.49013

где grid.head() основано на числовом эквиваленте графического представления grid

>>> grid
           x         y
0   0.000000 -9.490130 # the red dot
1   0.959131 -9.490130 # the bottom right blue square
2   1.918262 -9.490130
3   2.877393 -9.490130
4   3.836524 -9.490130
5   0.000000 -8.980486 # the middle left blue square
6   0.959131 -8.980486 # the green diamond
7   1.918262 -8.980486
8   2.877393 -8.980486
9   3.836524 -8.980486
10  0.000000 -8.470842 # the unwanted top left blue square
11  0.959131 -8.470842
12  1.918262 -8.470842
13  2.877393 -8.470842
14  3.836524 -8.470842

Таким образом, вам нужны точки 1, 5 и 6 в качестве окрестности точки 0.

Для этого вы можете взглянуть на функцию kneighbors_graph из модуль sklearn.neighbors, реализующий алгоритм k ближайших соседей. Поэкспериментируйте с ним и установите параметр мощности для метрики Минковского, p, больше 2, скажем, 3 (идея взять p>2 в основном состоит в том, чтобы уменьшить коэффициент евклидова квадратного корня из 2 - между диагоналями и сторонами в единичном квадрате - к 1), следующим образом

>>> from sklearn.neighbors import kneighbors_graph
>>> _3n_graph = kneighbors_graph(grid,
                                 n_neighbors=3,
                                 p=3,
                                 mode='connectivity',
                                 include_self=False)

урожаи

>>> grid.iloc[_3n_graph[0].indices]
          x         y
5  0.000000 -8.980486
1  0.959131 -9.490130
6  0.959131 -8.980486
person keepAlive    schedule 04.05.2017
comment
О боже! Прошу прощения, что не предоставил вам обратную связь ранее. По некоторым причинам я не получил уведомление, что вы ответили! Отличный ответ! Наконец (проект уже завершен), я выбрал более глобальный подход, если бы мог: я использовал scipy.interpolate.griddata вместо реализации моего собственного способа интерполяции данных на основе сетки. P.S. Извините за не минимальный, полный и проверяемый пример - person Alex; 09.05.2017
comment
@Alex Алекс Кажется, ты действительно превратил свою прямоугольную сетку в квадратную, не так ли? Так что даже при евклидовых расстояниях вы получали нужные вам очки. - person keepAlive; 09.05.2017
comment
Насколько я понимаю, scipy griddata может принимать практически все в качестве входной сетки, поэтому я оставил нетронутым то, что у меня было. - person Alex; 09.05.2017
comment
Я принял ваш ответ, потому что даже если я изменил свой код, он все равно отвечает на вопрос, который я задал! Спасибо еще раз - person Alex; 09.05.2017