Рассчитать расстояние до ближайшего объекта

Мне нужно составить карту расстояний до ближайшего объекта. У меня есть решение, в котором я просматриваю каждую точку карты и каждый объект, вычисляю расстояние до них всех, а затем оставляю только минимальное расстояние. Проблема здесь в том, что если я просыпаюсь с реальными данными, карта может легко содержать десятки миллионов точек, а объектов может быть более 100. Есть ли лучшая реализация кода для решения этой проблемы?

Загрузка пакетов

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

Создать синтетическую карту

coord_dict = {"X": [],
              "Y": []}

for x_value in range(0, 10000, 50):    
    for y_value in range(0, 5000, 50):
        coord_dict["X"].append(x_value)
        coord_dict["Y"].append(y_value)

map_df = pd.DataFrame(coord_dict)

Сгенерируйте точки для расчета расстояния от

well_points_dict = {"X": [500, 1500, 4000, 5500, 6250, 7500, 8000, 9000], 
                    "Y": [500, 4000, 2000, 1500, 500, 5000, 100, 2500]}

wells_df = pd.DataFrame(well_points_dict)

Рассчитать расстояния

calculations_count = 0
distance_map = np.zeros(map_df.shape)

for i in range(map_df.shape[0]):
    d = []
    for j in range(wells_df.shape[0]):
        d.append(((map_df["X"].iloc[i]-wells_df["X"][j])**2 + (map_df["Y"].iloc[i]-      wells_df["Y"][j])**2)**0.5)
        calculations_count += 1
    dd = min(d)
    distance_map[i,1] = dd
    # print(calculations_count)

Распечатать полученную карту

plt.figure(figsize=(10,10))
plt.scatter(x=map_df["X"],y=map_df["Y"],c=distance_map[:,1],s=1,cmap='terrain')
for i in range(len(wells_df)):
    plt.plot(wells_df["X"][i],wells_df["Y"][i], color='black', marker='o',markersize=3)
plt.title('Calculated map')
plt.xlabel('X')
plt.ylabel('Y')
plt.axis('scaled')
plt.tight_layout()
plt.colorbar(shrink=0.25)

Пример карты результатов:

Рассчитать расстояние до ближайшего объекта

«Оставляя только минимальное расстояние» -- Расстояние чего? Если вам нужно минимальное расстояние от каждой точки до каждой другой точки, то у вас нет другого выбора, кроме как попробовать их все, что вы и делаете.

Tim Roberts 25.06.2024 08:40

@TimRoberts, это неправда. В одном измерении вы можете отсортировать массив. В более высоких измерениях что-то вроде k-дерева дает грубый аналог, и существует множество приближений.

Danica 25.06.2024 08:51

Только бегло просмотрел, возможно, вы уже это делаете, просто убедитесь, что вы не вычисляете x->y и y->x.

NickSlash 25.06.2024 08:51
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
3
136
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

(Приблизительный) поиск ближайших соседей — обычная задача для множества библиотек. Удобное место для проверки — https://ann-benchmarks.com/ — лучший выбор зависит от ваших потребностей, но если у вас действительно есть 2D-данные с множеством точек, простое k-d дерево, скорее всего, ускорится. резко задавать вопросы, но при этом давать точные ответы. В более высоких измерениях вам, вероятно, придется отказаться от гарантированных точных ответов, но небольшое расслабление может дать вам огромный выигрыш в скорости.

Ответ принят как подходящий

KDTree - это то, что вы ищете, его реализация есть в scipy.spatial.

import numpy as np
import matplotlib.pyplot as plt
from scipy import spatial

Учитывая ваши пробные баллы:

x_value = np.arange(0, 10000, 50)  
y_value = np.arange(0, 5000, 50)
X, Y = np.meshgrid(x_value, y_value)
points = np.stack([X.ravel(), Y.ravel()]).T

И хорошие моменты:

x_well = np.array([500, 1500, 4000, 5500, 6250, 7500, 8000, 9000])
y_well = np.array([500, 4000, 2000, 1500, 500, 5000, 100, 2500])
wells = np.stack([x_well, y_well]).T

Мы можем создать KDTree:

interpolator = spatial.KDTree(wells)

И эффективно запросите дерево, чтобы получить расстояния, а также индексы того, какая точка ближе:

distances, indices = interpolator.query(points)
# 7.12 ms ± 711 µs per loop (mean ± std. dev. of 30 runs, 100 loops each)

Построение графика результатов приводит к:

fig, axe = plt.subplots()
axe.scatter(*points.T, marker = ".", c=distances)
axe.scatter(*wells.T, color = "black")
axe.grid()

Мы видим диаграмму Вороного, появляющуюся на цветовой карте, которая является хорошим подтверждением правильности интерпретации расстояний относительно контрольных точек (скважин):

voronoi = spatial.Voronoi(wells)
# ...
spatial.voronoi_plot_2d(voronoi, ax=axe)

Где объект Вороного - это диаграмма Вороного, основанная на ваших опорных точках (колодцах) и voronoi_plot_2d помощник для ее рисования по осям.

Спасибо! Это сработало отлично! Не знал про KDTree=)

Kekkerino_taco 25.06.2024 23:03

Другие вопросы по теме

Python Pandas: присоединение к регистронезависимому и лишенному ключу
Измените форму кадра данных Pandas и сгруппируйте столбцы двух уровней
Python: 3-сигма детектор «аномалий» количества заказов и строк
Как избежать цикла в Pandas, повторяющего уникальные значения?
Как исправить столбец с числовыми значениями, который воспринимается как строковое поле из-за пустых строк в фрейме данных Pandas?
Добавьте значения двух Dataframe на основе похожих значений строк
С помощью Python извлеките в файл Excel значение ячейки в строке, где ячейка в той же строке содержит строку символов из XML-файла
Обмен датой начала, датой окончания и другими столбцами с более ранней строкой, если даты больше 8 в фрейме данных pandas
Как я могу сравнить значение в одном столбце со всеми значениями, которые находятся ДО него в другом столбце, чтобы найти количество уникальных значений, которые меньше?
Присоединиться к фрейму данных с двойной записью