У меня есть две точки в 3D:
(xa, ya, za)
(xb, yb, zb)
И я хочу рассчитать расстояние:
dist = sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)
Какой лучший способ сделать это с NumPy или с Python в целом? Я имею:
import numpy
a = numpy.array((xa ,ya, za))
b = numpy.array((xb, yb, zb))
python
numpy
euclidean-distance
Натан Феллман
источник
источник
Для этого в SciPy есть функция. Это называется евклидово .
Пример:
источник
Для тех, кто заинтересован в одновременном вычислении нескольких расстояний, я провел небольшое сравнение с использованием perfplot (небольшой мой проект).
Первый совет состоит в том, чтобы организовать ваши данные таким образом, чтобы массивы имели размерность
(3, n)
(и, очевидно, C-смежны). Если добавление происходит в смежном первом измерении, все происходит быстрее, и это не имеет большого значения, если вы используетеsqrt-sum
сaxis=0
,linalg.norm
сaxis=0
иличто, с небольшим отрывом, самый быстрый вариант. (Это действительно справедливо только для одного ряда.)
Варианты, где вы суммируете по второй оси,
axis=1
все существенно медленнее.Код для воспроизведения сюжета:
источник
i,i->
data
должно выглядеть?Я хочу изложить простой ответ с различными заметками о производительности. np.linalg.norm сделает, возможно, больше, чем вам нужно:
Во-первых, эта функция предназначена для работы со списком и возврата всех значений, например, для сравнения расстояния
pA
до набора точекsP
:Помните несколько вещей:
Так
не так невинно, как кажется.
Во-первых - каждый раз, когда мы вызываем его, мы должны выполнить глобальный поиск для «np», поиск в области видимости для «linalg» и поиск в области видимости для «norm» и накладные расходы, связанные с простым вызовом функции могут равняться десяткам Python инструкции.
Наконец, мы потратили две операции, чтобы сохранить результат и перезагрузить его для возврата ...
Первый шаг к улучшению: сделайте поиск быстрее, пропустите магазин
Мы получаем гораздо более упорядоченный:
Затраты на вызов функции по-прежнему составляют некоторую работу. И вы захотите сделать тесты, чтобы определить, лучше ли вам делать математику самостоятельно:
На некоторых платформах
**0.5
это быстрее, чемmath.sqrt
. Ваш пробег может варьироваться.**** Расширенные заметки производительности.
Почему вы рассчитываете расстояние? Если единственной целью является его отображение,
двигаться вперед. Но если вы сравниваете расстояния, проводите проверки дальности и т. Д., Я хотел бы добавить некоторые полезные наблюдения за производительностью.
Давайте рассмотрим два случая: сортировка по расстоянию или отбор списка по элементам, которые соответствуют ограничению диапазона.
Первое, что нам нужно помнить, это то, что мы используем Pythagoras для вычисления расстояния (
dist = sqrt(x^2 + y^2 + z^2)
), поэтому мы делаем многоsqrt
вызовов. Математика 101:Короче говоря: пока нам не потребуется расстояние в единице X, а не X ^ 2, мы можем исключить самую сложную часть вычислений.
Отлично, обе функции больше не делают дорогих квадратных корней. Это будет намного быстрее. Мы также можем улучшить in_range, преобразовав его в генератор:
Это особенно полезно, если вы делаете что-то вроде:
Но если следующая вещь, которую вы собираетесь сделать, требует расстояния,
рассмотреть возможность получения кортежей:
Это может быть особенно полезно, если вы можете связать проверки диапазона («найдите вещи, которые находятся около X и в пределах Nm от Y», так как вам не нужно снова вычислять расстояние).
Но что делать, если мы ищем действительно большой список
things
и ожидаем, что многие из них не заслуживают рассмотрения?Там на самом деле очень простая оптимизация:
Будет ли это полезно, будет зависеть от размера «вещей».
И снова, рассмотрите возможность выдачи dist_sq. Наш пример хот-дога становится:
источник
pointZ
, чего не было. Я думаю, что вы имели в виду две точки в трехмерном пространстве, и я отредактировал соответственно. Если я ошибся, пожалуйста, дайте мне знать.Еще один пример этого метода решения проблем :
источник
norm = lambda x: N.sqrt(N.square(x).sum())
;norm(x-y)
numpy.linalg.norm(x-y)
Запуск
Python 3.8
, тоmath
модуль непосредственно обеспечиваетdist
функцию, которая возвращает евклидово расстояния между двумя точками ( с учетом как кортежи или списки координатов):И если вы работаете со списками:
источник
Это можно сделать следующим образом. Я не знаю, как это быстро, но он не использует NumPy.
источник
for a, b in zip(a, b)
. Но тем не менее полезно.Я нахожу функцию dist в matplotlib.mlab, но не думаю, что она достаточно удобна.
Я публикую это здесь только для справки.
источник
Мне нравится
np.dot
(точечный продукт):источник
Хороший однострочник:
Однако, если скорость вызывает беспокойство, я бы порекомендовал поэкспериментировать на вашей машине. Я обнаружил, что с помощью
math
библиотекиsqrt
с**
оператором для квадрата намного быстрее на моей машине, чем однострочное решение NumPy.Я провел свои тесты, используя эту простую программу:
На моей машине
math_calc_dist
работает намного быстрее чемnumpy_calc_dist
: 1,5 секунды против 23,5 секунды.Чтобы получить измеримую разницу между мной
fastest_calc_dist
иmath_calc_dist
мне нужно было доTOTAL_LOCATIONS
6000. Затемfastest_calc_dist
требуется ~ 50 секунд, аmath_calc_dist
занимает ~ 60 секунд.Вы также можете поэкспериментировать,
numpy.sqrt
иnumpy.square
хотя обаmath
варианта были медленнее, чем альтернативы на моей машине.Мои тесты были запущены с Python 2.6.6.
источник
scipy.spatial.distance.cdist(p1, p2).sum()
. Вот и все.numpy.linalg.norm(p1-p2).sum()
для получения суммы между каждой точкой в p1 и соответствующей точкой в p2 (то есть не каждой точкой в p1 для каждой точки в p2). И если вы хотите, чтобы каждая точка в p1 совпадала с каждой точкой в p2, и не хотите использовать scipy, как в моем предыдущем комментарии, тогда вы можете использовать np.apply_along_axis вместе с numpy.linalg.norm, чтобы делать это намного, намного быстрее тогда ваше "самое быстрое" решение.Вы можете просто вычесть векторы и затем получить внутренний продукт.
Следуя вашему примеру,
источник
Имея
a
иb
как вы их определили, вы также можете использовать:источник
С Python 3.8 это очень просто.
https://docs.python.org/3/library/math.html#math.dist
источник
Вот краткий код евклидова расстояния в Python с учетом двух точек, представленных в виде списков в Python.
источник
Начиная с Python 3.8
Начиная с Python 3.8
math
модуль включает в себя функциюmath.dist()
.Смотрите здесь https://docs.python.org/3.8/library/math.html#math.dist .
источник
Рассчитаем евклидово расстояние для многомерного пространства:
источник
источник
источник
Вы можете легко использовать формулу
что на самом деле не более чем использование теоремы Пифагора для вычисления расстояния путем сложения квадратов Δx, Δy и Δz и укоренения результата.
источник
Сначала найдите разницу двух матриц. Затем примените поэлементное умножение с помощью команды умножения numpy. После этого найдите суммирование умноженной на элемент новой матрицы. Наконец, найдите квадратный корень суммирования.
источник
Вы первый список изменений в Numpy массив и сделать так:
print(np.linalg.norm(np.array(a) - np.array(b)))
. Второй метод прямо из списка Python:print(np.linalg.norm(np.subtract(a,b)))
источник