Let’s not forget math.hypot:
dist = math.hypot(x2-x1, y2-y1)
Here’s hypot as part of a snippet to compute the length of a path defined by a list of (x, y) tuples:
from math import hypot
pts = [
(10,10),
(10,11),
(20,11),
(20,10),
(10,10),
]
# Py2 syntax - no longer allowed in Py3
# ptdiff = lambda (p1,p2): (p1[0]-p2[0], p1[1]-p2[1])
ptdiff = lambda p1, p2: (p1[0]-p2[0], p1[1]-p2[1])
diffs = (ptdiff(p1, p2) for p1, p2 in zip (pts, pts[1:]))
path = sum(hypot(*d) for d in diffs)
print(path)
In this tutorial, we will look at how to calculate the distance between two points in Python with the help of some examples.
If you prefer video over text, check out the following video detailing the steps in this tutorial –
There are a number of ways to compute the distance between two points in Python. You can compute the distance directly or use methods from libraries like math
, scipy
, numpy
, etc.
We generally refer to the Euclidean distance when talking about the distance between two points. To calculate the Euclidean distance between the points (x1, y1) and (x2, y2) you can use the formula:
For example, the distance between points (2, 3) and (5, 7) is 5. Note that the above formula can be extended to n-dimensions.
Euclidean distance in Python
Now that we know how the distance between two points is computed mathematically, we can proceed to compute it in Python.
Python has a number of libraries that help you compute distances between two points, each represented by a sequence of coordinates. Before we proceed to use off-the-shelf methods, let’s directly compute the distance between points (x1, y1) and (x2, y2).
# point a x1 = 2 y1 = 3 # point b x2 = 5 y2 = 7 # distance b/w a and b distance = ((x1 - x2)**2 + (y1 - y2)**2)**0.5 # display the result print("Distance between points ({}, {}) and ({}, {}) is {}".format(x1,y1,x2,y2,distance))
Output:
Distance between points (2, 3) and (5, 7) is 5.0
You can see that we get the distance between the points (2, 3) and (5, 7) as 5. Note that the above formula works only for points in two dimensions.
Let’s now write a generalized function that can handle points with any number of dimensions.
def get_distance(p, q): """ Return euclidean distance between points p and q assuming both to have the same number of dimensions """ # sum of squared difference between coordinates s_sq_difference = 0 for p_i,q_i in zip(p,q): s_sq_difference += (p_i - q_i)**2 # take sq root of sum of squared difference distance = s_sq_difference**0.5 return distance # check the function a = (2, 3, 6) b = (5, 7, 1) # distance b/w a and b d = get_distance(a, b) # display the result print(d)
Output:
7.0710678118654755
You can see that we used the function to get distance between two points with three dimensions each. We can now use this function to calculate distances between two points with any dimensions.
Note that the above function can further be improved by using vectorization to calculate the difference between the coordinates.
Euclidean distance using math
library
You can use the math.dist()
function to get the Euclidean distance between two points in Python. For example, let’s use it the get the distance between two 3-dimensional points each represented by a tuple.
import math # two points a = (2, 3, 6) b = (5, 7, 1) # distance b/w a and b d = math.dist(a, b) # display the result print(d)
Output:
7.0710678118654755
We get the same value as above.
Euclidean distance using numpy
library
The Euclidean distance is equivalent to the l2 norm of the difference between the two points which can be calculated in numpy using the numpy.linalg.norm()
function.
import numpy as np # two points a = np.array((2, 3, 6)) b = np.array((5, 7, 1)) # distance b/w a and b d = np.linalg.norm(a-b) # display the result print(d)
Output:
7.0710678118654755
We get the same result as above. Note that, here, we pass the difference between points a and b as a numpy array to the the np.linalg.norm()
function.
Euclidean distance using scipy
library
The scipy
library contains a number of useful functions of scientific computation in Python. Use the distance.euclidean()
function available in scipy.spatial
to calculate the Euclidean distance between two points in Python.
from scipy.spatial import distance # two points a = (2, 3, 6) b = (5, 7, 1) # distance b/w a and b d = distance.euclidean(a, b) # display the result print(d)
Output:
7.0710678118654755
We get the same result as above. For more on the distance function, refer to its documentation.
With this, we come to the end of this tutorial. The code examples and results presented in this tutorial have been implemented in a Jupyter Notebook with a python (version 3.8.3) kernel having numpy version 1.18.5 and pandas version 1.0.5
Subscribe to our newsletter for more informative guides and tutorials.
We do not spam and you can opt out any time.
-
Piyush is a data professional passionate about using data to understand things better and make informed decisions. He has experience working as a Data Scientist in the consulting domain and holds an engineering degree from IIT Roorkee. His hobbies include watching cricket, reading, and working on side projects.
View all posts
Время на прочтение
5 мин
Количество просмотров 28K
В этом руководстве мы рассмотрим, как рассчитать евклидово расстояние между двумя точками в Python с помощью Numpy.
Что такое евклидово расстояние?
Евклидово расстояние — это фундаментальная метрика расстояния, относящаяся к системам в евклидовом пространстве.
-
Евклидово пространство — это классическое геометрическое пространство, с которым вы знакомитесь на уроке математики, обычно связанное с 3 измерениями. Хотя его также можно приписать к любой неотрицательной целочисленной размерности.
-
Евклидово расстояние — кратчайшая прямая между двумя точками в евклидовом пространстве.
Название происходит от Евклида, который широко известен как «отец геометрии», так как это было единственное пространство, которое люди в то время обычно задумывали. Со временем в физике и математике наблюдались различные типы пространства, такие как пространство Аффин.
-
В 3-мерном евклидовом пространстве кратчайшая прямая между двумя точками всегда будет прямой линией между ними.
Учитывая этот факт, евклидово расстояние не всегда является наиболее полезной метрикой для отслеживания при работе со многими размерностями, мы сосредоточимся на 2D и 3D евклидовом пространстве для расчета евклидова расстояния.
Вообще говоря, евклидова расстояние широко используется в разработке 3D-миров, а также алгоритмов машинного обучения, которые включают в себя метрики расстояния, такие как K-ближайшие соседи. Как правило, евклидово расстояние будет представлять, насколько похожи две точки данных, предполагая, что некоторая кластеризация на основе других данных уже была выполнена.
Математическая формула
Математическая формула расчета евклидова расстояния между 2 точками в 2D пространстве:
Формула легко адаптируется к 3D-пространство, а также к любому размеру:
Общая формула может быть упрощена до:
Острый глаз может заметить сходство между евклидовым расстоянием и теоремой Пифагора:
На самом деле существует связь между ними — евклидовое расстояние рассчитывается с помощью теоремы Пифагора, учитывая декартовы координаты двух точек.
Из-за этого евклидова расстояние иногда называют расстоянием Пифагора, хотя прежнее название гораздо более известно.
Примечание: Две точки являются векторами, но выход должен быть скалярным.
Мы будем использовать NumPy для расчета этого расстояния для двух точек, и один и тот же подход используется для 2D и 3D пространств:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
ax.scatter(0, 0, 0)
ax.scatter(3, 3, 3)
plt.show()
Расчет евклидова расстояния в Python с помощью NumPy
Во-первых, нам нужно будет установить библиотеку NumPy:
$ pip install numpy
Теперь давайте импортируем его и настроим две наши точки с декартовыми координатами (0, 0, 0) и (3, 3, 3):
import numpy as np
# Initializing the points
point_1 = np.array((0, 0, 0))
point_2 = np.array((3, 3, 3))
Вместо того, чтобы выполнять расчет вручную, мы будем использовать вспомогательные методы NumPy, чтобы сделать его еще проще!
np.sqrt() и np.sum()
Операции и математические функции, необходимые для расчета евклидова расстояния, довольно просты: сложение, вычитание, а также функция квадратного корня. Несколько слагаемых также можно заменить суммой:
NumPy предоставляет нам функцию np.sqrt(), представляющую функцию квадратного корня, а также функцию np.sum(), которая представляет собой сумму. При этом расчет евклидова расстояния в Python прост и интуитивно понятен:
# Get the square of the difference of the 2 vectors
square = np.square(point_1 - point_2)
# Get the sum of the square
sum_square = np.sum(square)
Данная формула дает нам довольно простой результат:
(0-3)^2 + (0-3)^2 + (0-3)^2
Что равно 27. Осталось все, что получить квадратный корень из этого числа:
# The last step is to get the square root and print the Euclidean distance
distance = np.sqrt(sum_square)
print(distance)
Это приводит к:
5.196152422706632
В истинном питоновом духе это можно сократить до одной строки:
И вы даже можете вместо этого использовать встроенные методы pow() и sum() математического модуля Python, хотя они требуют, чтобы вы немного поработали с вводом, который удобно абстрагируется с помощью NumPy, так как функция pow() работает только со скалярами (каждый элемент в массиве индивидуально) и принимает аргумент — в какой степени вы увеличиваете число.
Этот подход, однако, интуитивно больше похож на формулу, которую мы использовали раньше:
from math import *
distance = np.sqrt(sum(pow(a-b, 2) for a, b in zip(point_1, point_2)))
print(distance)
Это также приводит к:
5.196152422706632
np.linalg.norm()
Функция np.linalg.norm() представляет математическую норму. По сути, нормой вектора является его длина. Эта длина не обязательно должна быть евклидовым расстоянием, а может быть и другими расстояниями. Евклидово расстояние-это норма L2 вектора (иногда известная как евклидова норма), и по умолчанию функция norm() использует L2 — параметр ord имеет значение 2.
Если бы вы установили для параметра ord какое-то другое значение p, вы бы рассчитали другие p-нормы. Например, норма L1 вектора-это расстояние Манхэттена!
Имея это в виду, мы можем использовать функцию np.linalg.norm() для легкого и гораздо более чистого вычисления евклидова расстояния, чем использование других функций:
distance = np.linalg.norm(point_1-point_2)
print(distance)
Это приводит к печати расстояния L2/евклида:
5.196152422706632
Нормализация L2 и нормализация L1 широко используются в машинном обучении для нормализации входных данных.
np.dot()
Мы также можем использовать точечное произведение для расчета евклидова расстояния. В математике точечное произведение является результатом умножения двух векторов равной длины, а результатом является единственное число — скалярное значение. Из-за возвращаемого типа его иногда также называют «скалярным продуктом». Эту операцию часто называют внутренним произведением для двух векторов.
Для расчета точечного произведения между 2 векторами вы можете использовать следующую формулу:
С помощью NumPy мы можем использовать функцию np.dot(), передавая два вектора.
Если мы вычислим точечное произведение разницы между обеими точками с той же разницей — мы получим число, которое находится в зависимости от евклидова расстояния между этими двумя векторами. Извлечение квадратного корня из этого числа дает нам расстояние, которое мы ищем:
# Take the difference between the 2 points
diff = point_1 - point_2
# Perform the dot product on the point with itself to get the sum of the squares
sum_square = np.dot(diff, diff)
# Get the square root of the result
distance = np.sqrt(sum_square)
print(distance)
Конечно, вы также можете сократить это до однострочного:
distance = np.sqrt(np.dot(point_1-point_2, point_1-point_2))
print(distance)
5.196152422706632
Использование встроенной системы math.dist()
В Python есть встроенный метод в математическом модуле, который вычисляет расстояние между 2 точками в трехмерном пространстве. Однако это работает только с Python 3.8 или более поздней версии.
math.dist()принимает два параметра, которые являются двумя точками, и возвращает евклидово расстояние между этими точками.
Примечание: Обратите внимание, что две точки должны иметь одинаковые размеры (т.е. оба в 2d или 3d пространстве).
Теперь, чтобы вычислить Евклидово расстояние между этими двумя точками, мы просто заправляем их в метод thedistdist():
import math
distance = math.dist(point_1, point_2)
print(distance)
5.196152422706632
Заключение
Данная метрика используется во многих контекстах в интеллектуальном анализе данных, машинном обучении и ряде других областей и является одной из фундаментальных метрик расстояния.
В этом уроке мы обсудим различные методы, с помощью которых пользователь может рассчитать расстояние между двумя местами на Земле. geopy – это библиотека Python, которая помогает рассчитать географическое расстояние.
Сначала нужно установить geopy с помощью следующей команды:
pip install geopy
После успешной установки мы готовы к работе с библиотекой geopy.
Вычисление расстояния между двумя точками
Ниже приведены важные методы, которые мы будем использовать, чтобы рассчитать расстояние между двумя точками с помощью GEOPY в Python:
- Метод 1: с использованием геодезического расстояния
Геодезическое расстояние – это длина кратчайшего пути между двумя точками на любой поверхности Земли. В следующем примере мы покажем, как пользователь может вычислить геодезическое расстояние на основе данных широты и долготы.
Пример:
# First, import the geodesic module from the geopy library from geopy.distance import geodesic as GD # Then, load the latitude and longitude data for New York & Texas New_York = (40.7128, 74.0060) Texas = (31.9686, 99.9018) # At last, print the distance between two points calculated in kilo-metre print ("The distance between New York and Texas is: ", GD(New_York, Texas).km)
Выход:
The distance between New York and Texas is: 2507.14797665193
- Метод 2: с использованием расстояния по большому кругу
Расстояние по большому кругу – это кратчайший путь между двумя точками на сфере. В этом случае мы предположим, что Земля – это идеальная сфера. В следующем примере показано, как пользователь может рассчитать расстояние по большому кругу, используя данные долготы и широты двух точек.
Пример:
# First, import the great_circle module from the geopy library from geopy.distance import great_circle as GC # Then, load the latitude and longitude data for New York & Texas New_York = (40.7128, 74.0060) Texas = (31.9686, 99.9018) # At last, print the distance between two points calculated in kilo-metre print ("The distance between New York and Texas is: ", GC(New_York, Texas).km)
Выход:
The distance between New York and Texas is: 2503.045970189156
- Метод 3: с использованием формулы гаверсинуса
Ортодромическое расстояние используется для вычисления кратчайшего расстояния между двумя точками широты и долготы на поверхности земли.
Используя этот метод, пользователю необходимо иметь координаты двух точек (P и Q).
Сначала нужно преобразовать значения точек широты и долготы из десятичных градусов в радианы, а затем разделить значения широты и долготы на (180 / π). Пользователь должен использовать значение «π = 22/7». Тогда значение (180 / π) будет «57,29577». Если пользователь хочет рассчитать расстояние в милях, он может использовать значение радиуса Земли, то есть «3963», а если в километрах – использовать значение «6,378,80».
Формулы:
How to calculate the value of latitude in radians: The value of Latitude in Radian: Latitude (La1) = La1 / (180/?) OR The value of Latitude in Radian: Latitude (La1) = La1 / 57.29577 How to calculate the value of longitude in radians: The value of Longitude in Radian: Longitude (Lo1) = Lo1 / (180/?) OR The value of Longitude in Radian: Longitude (Lo1) = Lo1 / 57.29577
Пользователю нужны координаты точки P и точки Q с точки зрения долготы и широты, а затем необходимо использовать приведенную выше формулу для преобразования их в радианы.
Теперь рассчитаем расстояние между двумя точками по следующей формуле.
Формула:
Для миль:
Distance (D) = 3963.0 * arccos[(sin(La1) * sin(La2)) + cos(La1) * cos(La2) * cos(Lo2 - Lo1)]
Для километров:
Distance (D) = 3963.0 * arccos[(sin(La1) * sin(La2)) + cos(La1) * cos(La2) * cos(Lo2 - Lo1)]
Таким образом, пользователь может рассчитать кратчайшее расстояние между двумя заданными точками на Земле с помощью формулы гаверсинуса.
Пример:
from math import radians, cos, sin, asin, sqrt # For calculating the distance in Kilometres def distance_1(La1, La2, Lo1, Lo2): # The math module contains the function name "radians" which is used for converting the degrees value into radians. Lo1 = radians(Lo1) Lo2 = radians(Lo2) La1 = radians(La1) La2 = radians(La2) # Using the "Haversine formula" D_Lo = Lo2 - Lo1 D_La = La2 - La1 P = sin(D_La / 2)**2 + cos(La1) * cos(La2) * sin(D_Lo / 2)**2 Q = 2 * asin(sqrt(P)) # The radius of earth in kilometres. R_km = 6371 # Then, we will calculate the result return(Q * R_km) # driver code La1 = 40.7128 La2 = 31.9686 Lo1 = -74.0060 Lo2 = -99.9018 print ("The distance between New York and Texas is: ", distance_1(La1, La2, Lo1, Lo2), "K.M") # For calculating the distance in Miles def distance_2(La1, La2, Lo1, Lo2): # The math module contains the function name "radians" which is used for converting the degrees value into radians. Lo1 = radians(Lo1) Lo2 = radians(Lo2) La1 = radians(La1) La2 = radians(La2) # Using the "Haversine formula" D_Lo = Lo2 - Lo1 D_La = La2 - La1 P = sin(D_La / 2)**2 + cos(La1) * cos(La2) * sin(D_Lo / 2)**2 Q = 2 * asin(sqrt(P)) # The radius of earth in Miles. R_Mi = 3963 # Then, we will calculate the result return(Q * R_Mi) print ("The distance between New York and Texas is: ", distance_2(La1, La2, Lo1, Lo2), "Miles")
Выход:
The distance between New York and Texas is: 2503.04243426357 K.M The distance between New York and Texas is: 1556.985899699659 Miles
В этом уроке мы обсудили различные методы расчета расстояния между двумя точками на поверхности земли с помощью библиотеки geopy и показали примеры каждого метода.
Изучаю Python вместе с вами, читаю, собираю и записываю информацию опытных программистов.
I need to take a list I have created and find the closest two points and print them out. How can I go about comparing each point in the list?
There isn’t any need to plot or anything, just compare the points and find the closest two in the list.
import math # 'math' needed for 'sqrt'
# Distance function
def distance(xi,xii,yi,yii):
sq1 = (xi-xii)*(xi-xii)
sq2 = (yi-yii)*(yi-yii)
return math.sqrt(sq1 + sq2)
# Run through input and reorder in [(x, y), (x,y) ...] format
oInput = ["9.5 7.5", "10.2 19.1", "9.7 10.2"] # Original input list (entered by spacing the two points).
mInput = [] # Manipulated list
fList = [] # Final list
for o in oInput:
mInput = o.split()
x,y = float(mInput[0]), float(mInput[1])
fList += [(x, y)] # outputs [(9.5, 7.5), (10.2, 19.1), (9.7, 10.2)]
asked Mar 23, 2011 at 15:50
It is more convenient to rewrite your distance()
function to take two (x, y)
tuples as parameters:
def distance(p0, p1):
return math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)
Now you want to iterate over all pairs of points from your list fList
. The function iterools.combinations()
is handy for this purpose:
min_distance = distance(fList[0], fList[1])
for p0, p1 in itertools.combinations(fList, 2):
min_distance = min(min_distance, distance(p0, p1))
An alternative is to define distance()
to accept the pair of points in a single parameter
def distance(points):
p0, p1 = points
return math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)
and use the key
parameter to the built-in min()
function:
min_pair = min(itertools.combinations(fList, 2), key=distance)
min_distance = distance(min_pair)
answered Mar 23, 2011 at 15:58
Sven MarnachSven Marnach
567k117 gold badges934 silver badges834 bronze badges
7
I realize that there are library constraints on this question, but for completeness if you have N
points in an Nx2 numpy ndarray (2D system):
from scipy.spatial.distance import pdist
x = numpy.array([[9.5,7.5],[10.2,19.1],[9.7,10.2]])
mindist = numpy.min(pdist(x))
I always try to encourage people to use numpy/scipy if they are dealing with data that is best stored in a numerical array and it’s good to know that the tools are out there for future reference.
answered Mar 23, 2011 at 17:40
JoshAdelJoshAdel
66.3k26 gold badges140 silver badges140 bronze badges
Note that the math.sqrt
function is both slow and, in this case, unnecessary. Try comparing the distance squared to speed it up (sorting distances vs. distance squared will always produce the same ordering):
def distSquared(p0, p1):
return (p0[0] - p1[0])**2 + (p0[1] - p1[1])**2
answered Mar 23, 2011 at 16:05
Aaron DufourAaron Dufour
17.2k1 gold badge47 silver badges68 bronze badges
This might work:
oInput = ["9.5 7.5", "10.2 19.1", "9.7 10.2"]
# parse inputs
inp = [(float(j[0]), float(j[1])) for j in [i.split() for i in oInput]]
# initialize results with a really large value
min_distance = float('infinity')
min_pair = None
# loop over inputs
length = len(inp)
for i in xrange(length):
for j in xrange(i+1, length):
point1 = inp[i]
point2 = inp[j]
if math.hypot(point1[0] - point2[0], point1[1] - point2[0]) < min_distance:
min_pair = [point1, point2]
once the loops are done, min_pair should be the pair with the smallest distance.
Using float() to parse the text leaves room for improvement.
math.hypot is about a third faster than calculating the distance in a handwritten python-function
answered Mar 23, 2011 at 16:20
HumanCatfoodHumanCatfood
9611 gold badge7 silver badges20 bronze badges
Your fixed code. No efficient algorithm, just the brute force one.
import math # math needed for sqrt
# distance function
def dist(p1, p2):
return math.sqrt((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2)
# run through input and reorder in [(x, y), (x,y) ...] format
input = ["9.5 7.5", "10.2 19.1", "9.7 10.2"] # original input list (entered by spacing the two points)
points = [map(float, point.split()) for point in input] # final list
# http://en.wikipedia.org/wiki/Closest_pair_of_points
mindist = float("inf")
for p1, p2 in itertools.combinations(points, 2):
if dist(p1, p2) < mindist:
mindist = dist(p1, p2)
closestpair = (p1, p2)
print(closestpair)
answered Mar 23, 2011 at 16:06
orlporlp
112k36 gold badges215 silver badges312 bronze badges
5
First, some notes:
a**2 # squares a
(xi - xii)**2 # squares the expression in parentheses.
mInput doesn’t need to be declared in advance.
fList.append((x, y))
is more pythonic than using +=
.
Now you have fList
. Your distance function can be rewritten to take 2 2-tuple (point) arguments, which I won’t bother with here.
Then you can just write:
shortest = float('inf')
for pair in itertools.combinations(fList, 2):
shortest = min(shortest, distance(*pair))
answered Mar 23, 2011 at 16:03
nmichaelsnmichaels
49.2k12 gold badges106 silver badges135 bronze badges
3
Many of the above questions suggest finding square root using math.sqrt
which is slow as well as not a good approach to find square root. In spite of using such approach just recall the basic concepts from school: think of taking the square root of any positive number, x. The square root is then written as a power of one-half: x½. Thus, a fractional exponent indicates that some root is to be taken.
so rather than using math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)
Use
def distance(a,b):
euclidean_distance = ((b[0]-a[0])**2 + (a[1]-a[1])**2)**0.5
return(euclidean_distance)
Hope it helps
answered Apr 17, 2020 at 13:14