Làm thế nào có thể tính khoảng cách Euclide với NumPy?


529

Tôi có hai điểm trong 3D:

(xa, ya, za)
(xb, yb, zb)

Và tôi muốn tính khoảng cách:

dist = sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)

Cách tốt nhất để làm điều này với NumPy hoặc với Python nói chung là gì? Tôi có:

import numpy
a = numpy.array((xa ,ya, za))
b = numpy.array((xb, yb, zb))

Câu trả lời:


885

Sử dụng numpy.linalg.norm:

dist = numpy.linalg.norm(a-b)

Bạn có thể tìm thấy lý thuyết đằng sau điều này trong Giới thiệu về Khai thác dữ liệu

Điều này hoạt động vì khoảng cách Euclideđịnh mức l2 và giá trị mặc định của tham số ord trong numpy.linalg.norm là 2.

nhập mô tả hình ảnh ở đây


13
Các tài liệu linalg.norm có thể được tìm thấy ở đây: docs.scipy.org/doc/numpy/reference/generated/ nam Nhận xét thực sự duy nhất của tôi là chỉ ra mối liên hệ giữa một quy tắc (trong trường hợp này là định mức Frobenius / 2-Norm đó là mặc định cho hàm định mức) và số liệu (trong trường hợp này là khoảng cách Euclide).
Đánh dấu Lavin

7
Nếu OP muốn tính khoảng cách giữa một mảng tọa độ thì cũng có thể sử dụng scipy.spatial.distance.cdist .
mnky9800n

2
Câu hỏi của tôi là: tại sao sử dụng điều này ngược lại với điều này? stackoverflow.com/a/21986532/189411 từ scipy.spatial khoảng cách nhập a = (1,2,3) b = (4,5,6) dst = distance.euclidean (a, b)
Domenico Monaco

2
liên kết được cập nhật đến chức năng cdist của SciPy: docs.scipy.org/doc/scipy/reference/generated/ trộm
Steven C. Howell

thậm chí còn có nhiều phương thức nhanh hơn numpy.linalg.norm: semantive.com/blog/ Khăn
Muhammad Ashfaq

161

Có một chức năng cho điều đó trong SciPy. Nó được gọi là Euclide .

Thí dụ:

from scipy.spatial import distance
a = (1, 2, 3)
b = (4, 5, 6)
dst = distance.euclidean(a, b)

56
Nếu bạn tìm kiếm hiệu quả, tốt hơn là sử dụng chức năng numpy. Khoảng cách scipy chậm gấp đôi so với numpy.linalg.norm (ab) (và numpy.sqrt (numpy.sum ((ab) ** 2))). Trên máy của tôi, tôi nhận được 19,7 Lời nói với scipy (v0.15.1) và 8,9 bản với numpy (v1.9.2). Không phải là một sự khác biệt có liên quan trong nhiều trường hợp nhưng nếu trong vòng lặp có thể trở nên quan trọng hơn. Từ một cái nhìn nhanh chóng về mã scipy, nó dường như chậm hơn bởi vì nó xác nhận mảng trước khi tính toán khoảng cách.
Algold

@MikePalmice có, các chức năng scipy hoàn toàn tương thích với numpy. Nhưng hãy xem những gì aigold gợi ý ở đây (tất nhiên cũng hoạt động trên mảng numpy)
Avision

@Avision không chắc nó có hoạt động với tôi không vì ma trận của tôi có số lượng hàng khác nhau; cố gắng trừ chúng để có được một ma trận không hoạt động
Người hâm mộ số một của Bjork

@MikePalmice chính xác những gì bạn đang cố gắng tính toán với hai ma trận này? đầu vào / đầu ra dự kiến ​​là gì?
Avision

ty để theo dõi. Có một mô tả ở đây: stats.stackexchange.com/questions/322620/ săn . Tôi có 2 bảng 'hoạt động'; mỗi bộ có một nhãn 'mã', nhưng hai bộ nhãn hoàn toàn khác nhau. Mục tiêu của tôi là tìm mã tốt nhất hoặc gần nhất từ ​​bảng thứ hai tương ứng với mã cố định trong bảng đầu tiên (tôi biết câu trả lời nên là gì khi kiểm tra thủ công, nhưng muốn mở rộng lên đến hàng trăm bảng sau). Vì vậy, tập hợp con đầu tiên được cố định; Tôi tính toán avg euclid dist bw này và tất cả các tập hợp mã của thứ 2, sau đó sắp xếp
Người hâm mộ số một của Bjork

108

Đối với bất kỳ ai quan tâm đến việc tính toán nhiều khoảng cách cùng một lúc, tôi đã thực hiện một so sánh nhỏ bằng cách sử dụng perfplot (một dự án nhỏ của tôi).

Lời khuyên đầu tiên là tổ chức dữ liệu của bạn sao cho các mảng có thứ nguyên (3, n)(và rõ ràng là tiếp giáp C). Nếu việc thêm xảy ra ở chiều thứ nhất liền kề, mọi thứ sẽ nhanh hơn và không quá quan trọng nếu bạn sử dụng sqrt-sumvới axis=0, linalg.normvới axis=0, hoặc

a_min_b = a - b
numpy.sqrt(numpy.einsum('ij,ij->j', a_min_b, a_min_b))

đó là, bởi một biên độ nhỏ, biến thể nhanh nhất. (Điều đó thực sự đúng cho chỉ một hàng là tốt.)

Các biến thể nơi bạn tổng hợp trên trục thứ hai axis=1, tất cả đều chậm hơn.

nhập mô tả hình ảnh ở đây


Mã để tái tạo cốt truyện:

import numpy
import perfplot
from scipy.spatial import distance


def linalg_norm(data):
    a, b = data[0]
    return numpy.linalg.norm(a - b, axis=1)


def linalg_norm_T(data):
    a, b = data[1]
    return numpy.linalg.norm(a - b, axis=0)


def sqrt_sum(data):
    a, b = data[0]
    return numpy.sqrt(numpy.sum((a - b) ** 2, axis=1))


def sqrt_sum_T(data):
    a, b = data[1]
    return numpy.sqrt(numpy.sum((a - b) ** 2, axis=0))


def scipy_distance(data):
    a, b = data[0]
    return list(map(distance.euclidean, a, b))


def sqrt_einsum(data):
    a, b = data[0]
    a_min_b = a - b
    return numpy.sqrt(numpy.einsum("ij,ij->i", a_min_b, a_min_b))


def sqrt_einsum_T(data):
    a, b = data[1]
    a_min_b = a - b
    return numpy.sqrt(numpy.einsum("ij,ij->j", a_min_b, a_min_b))


def setup(n):
    a = numpy.random.rand(n, 3)
    b = numpy.random.rand(n, 3)
    out0 = numpy.array([a, b])
    out1 = numpy.array([a.T, b.T])
    return out0, out1


perfplot.save(
    "norm.png",
    setup=setup,
    n_range=[2 ** k for k in range(22)],
    kernels=[
        linalg_norm,
        linalg_norm_T,
        scipy_distance,
        sqrt_sum,
        sqrt_sum_T,
        sqrt_einsum,
        sqrt_einsum_T,
    ],
    logx=True,
    logy=True,
    xlabel="len(x), len(y)",
)

3
Cảm ơn bạn. Tôi đã học được một cái gì đó mới ngày hôm nay! Đối với mảng một chiều, chuỗi sẽ lài,i->
Tirtha R

4
Sẽ tuyệt vời hơn bao giờ hết nếu có sự so sánh giữa các giả định về bộ nhớ
dragonLOLz 17/2/19

Tôi muốn sử dụng mã của bạn nhưng tôi đang vật lộn với việc hiểu cách thức dữ liệu được tổ chức. Bạn có thể đưa ra một ví dụ không? Làm thế nào datađể phải trông như thế nào?
Julian Wiesner

1
Dự án thực sự gọn gàng và phát hiện. Tôi đã thực hiện một số âm mưu nửa vời, có cùng bản chất, vì vậy tôi nghĩ rằng tôi sẽ chuyển sang dự án của bạn và đóng góp sự khác biệt, nếu bạn thích chúng.
Nhà vật lý điên

42

Tôi muốn giải thích về câu trả lời đơn giản với các ghi chú hiệu suất khác nhau. np.linalg.norm sẽ làm nhiều hơn bạn cần:

dist = numpy.linalg.norm(a-b)

Thứ nhất - chức năng này được thiết kế để hoạt động trên một danh sách và trả về tất cả các giá trị, ví dụ để so sánh khoảng cách từ pAđến tập hợp các điểm sP:

sP = set(points)
pA = point
distances = np.linalg.norm(sP - pA, ord=2, axis=1.)  # 'distances' is a list

Ghi nhớ một số điều:

  • Các cuộc gọi hàm Python rất tốn kém.
  • [Thường xuyên] Python không tra cứu tên bộ đệm.

Vì thế

def distance(pointA, pointB):
    dist = np.linalg.norm(pointA - pointB)
    return dist

không ngây thơ như vẻ ngoài của nó

>>> dis.dis(distance)
  2           0 LOAD_GLOBAL              0 (np)
              2 LOAD_ATTR                1 (linalg)
              4 LOAD_ATTR                2 (norm)
              6 LOAD_FAST                0 (pointA)
              8 LOAD_FAST                1 (pointB)
             10 BINARY_SUBTRACT
             12 CALL_FUNCTION            1
             14 STORE_FAST               2 (dist)

  3          16 LOAD_FAST                2 (dist)
             18 RETURN_VALUE

Đầu tiên - mỗi khi chúng ta gọi nó, chúng ta phải thực hiện tra cứu toàn cầu cho "np", một tìm kiếm có phạm vi cho "linalg" và một tìm kiếm có phạm vi cho "định mức" và chi phí đơn giản là gọi hàm có thể tương đương với hàng chục con trăn hướng dẫn.

Cuối cùng, chúng tôi đã lãng phí hai thao tác để lưu trữ kết quả và tải lại để trả lại ...

Vượt qua đầu tiên ở cải tiến: làm cho việc tra cứu nhanh hơn, bỏ qua cửa hàng

def distance(pointA, pointB, _norm=np.linalg.norm):
    return _norm(pointA - pointB)

Chúng tôi nhận được sắp xếp hợp lý hơn nhiều:

>>> dis.dis(distance)
  2           0 LOAD_FAST                2 (_norm)
              2 LOAD_FAST                0 (pointA)
              4 LOAD_FAST                1 (pointB)
              6 BINARY_SUBTRACT
              8 CALL_FUNCTION            1
             10 RETURN_VALUE

Tuy nhiên, chức năng gọi qua chức năng vẫn lên tới một số công việc. Và bạn sẽ muốn làm điểm chuẩn để xác định xem bạn có thể tự mình làm toán tốt hơn không:

def distance(pointA, pointB):
    return (
        ((pointA.x - pointB.x) ** 2) +
        ((pointA.y - pointB.y) ** 2) +
        ((pointA.z - pointB.z) ** 2)
    ) ** 0.5  # fast sqrt

Trên một số nền tảng, **0.5là nhanh hơn math.sqrt. Số dặm của bạn có thể thay đổi.

**** Ghi chú hiệu suất nâng cao.

Tại sao bạn tính khoảng cách? Nếu mục đích duy nhất là hiển thị nó,

 print("The target is %.2fm away" % (distance(a, b)))

di chuyển dọc. Nhưng nếu bạn đang so sánh khoảng cách, thực hiện kiểm tra phạm vi, v.v., tôi muốn thêm một số quan sát hiệu suất hữu ích.

Chúng ta hãy thực hiện hai trường hợp: sắp xếp theo khoảng cách hoặc loại bỏ danh sách thành các mục đáp ứng ràng buộc phạm vi.

# Ultra naive implementations. Hold onto your hat.

def sort_things_by_distance(origin, things):
    return things.sort(key=lambda thing: distance(origin, thing))

def in_range(origin, range, things):
    things_in_range = []
    for thing in things:
        if distance(origin, thing) <= range:
            things_in_range.append(thing)

Điều đầu tiên chúng ta cần nhớ là chúng ta đang sử dụng Pythagoras để tính khoảng cách ( dist = sqrt(x^2 + y^2 + z^2)) vì vậy chúng ta đang thực hiện rất nhiều sqrtcuộc gọi. Toán 101:

dist = root ( x^2 + y^2 + z^2 )
:.
dist^2 = x^2 + y^2 + z^2
and
sq(N) < sq(M) iff M > N
and
sq(N) > sq(M) iff N > M
and
sq(N) = sq(M) iff N == M

Tóm lại: cho đến khi chúng tôi thực sự yêu cầu khoảng cách trong một đơn vị X chứ không phải X ^ 2, chúng tôi có thể loại bỏ phần khó nhất trong các phép tính.

# Still naive, but much faster.

def distance_sq(left, right):
    """ Returns the square of the distance between left and right. """
    return (
        ((left.x - right.x) ** 2) +
        ((left.y - right.y) ** 2) +
        ((left.z - right.z) ** 2)
    )

def sort_things_by_distance(origin, things):
    return things.sort(key=lambda thing: distance_sq(origin, thing))

def in_range(origin, range, things):
    things_in_range = []

    # Remember that sqrt(N)**2 == N, so if we square
    # range, we don't need to root the distances.
    range_sq = range**2

    for thing in things:
        if distance_sq(origin, thing) <= range_sq:
            things_in_range.append(thing)

Tuyệt vời, cả hai chức năng không còn làm bất kỳ căn bậc hai đắt tiền. Điều đó sẽ nhanh hơn nhiều. Chúng tôi cũng có thể cải thiện in_range bằng cách chuyển đổi nó thành trình tạo:

def in_range(origin, range, things):
    range_sq = range**2
    yield from (thing for thing in things
                if distance_sq(origin, thing) <= range_sq)

Điều này đặc biệt có lợi ích nếu bạn đang làm một cái gì đó như:

if any(in_range(origin, max_dist, things)):
    ...

Nhưng nếu điều tiếp theo bạn sẽ làm đòi hỏi một khoảng cách,

for nearby in in_range(origin, walking_distance, hotdog_stands):
    print("%s %.2fm" % (nearby.name, distance(origin, nearby)))

xem xét năng suất bộ:

def in_range_with_dist_sq(origin, range, things):
    range_sq = range**2
    for thing in things:
        dist_sq = distance_sq(origin, thing)
        if dist_sq <= range_sq: yield (thing, dist_sq)

Điều này có thể đặc biệt hữu ích nếu bạn có thể kiểm tra phạm vi chuỗi ('tìm những thứ ở gần X và trong Nm của Y', vì bạn không phải tính lại khoảng cách).

Nhưng nếu chúng ta đang tìm kiếm một danh sách thực sự lớn thingsvà chúng ta dự đoán rất nhiều trong số chúng không đáng để xem xét thì sao?

Thực sự có một tối ưu hóa rất đơn giản:

def in_range_all_the_things(origin, range, things):
    range_sq = range**2
    for thing in things:
        dist_sq = (origin.x - thing.x) ** 2
        if dist_sq <= range_sq:
            dist_sq += (origin.y - thing.y) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.z - thing.z) ** 2
                if dist_sq <= range_sq:
                    yield thing

Điều này có hữu ích hay không sẽ phụ thuộc vào kích thước của 'vật'.

def in_range_all_the_things(origin, range, things):
    range_sq = range**2
    if len(things) >= 4096:
        for thing in things:
            dist_sq = (origin.x - thing.x) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.y - thing.y) ** 2
                if dist_sq <= range_sq:
                    dist_sq += (origin.z - thing.z) ** 2
                    if dist_sq <= range_sq:
                        yield thing
    elif len(things) > 32:
        for things in things:
            dist_sq = (origin.x - thing.x) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.y - thing.y) ** 2 + (origin.z - thing.z) ** 2
                if dist_sq <= range_sq:
                    yield thing
    else:
        ... just calculate distance and range-check it ...

Và một lần nữa, hãy xem xét mang lại dist_sq. Ví dụ hotdog của chúng tôi sau đó trở thành:

# Chaining generators
info = in_range_with_dist_sq(origin, walking_distance, hotdog_stands)
info = (stand, dist_sq**0.5 for stand, dist_sq in info)
for stand, dist in info:
    print("%s %.2fm" % (stand, dist))

1
Tại sao không thêm một chức năng tối ưu hóa như vậy để numpy? Một tiện ích mở rộng cho gấu trúc cũng sẽ rất tuyệt vời cho một câu hỏi như stackoverflow.com/questions/47643952/ mẹo
Keith

3
Tôi chỉnh sửa phương pháp toán học đầu tiên của bạn để khoảng cách. Bạn đang sử dụng một pointZthứ không tồn tại. Tôi nghĩ những gì bạn có nghĩa là hai điểm trong không gian ba chiều và tôi đã chỉnh sửa tương ứng. Nếu tôi sai, xin vui lòng cho tôi biết.
Bram Vanroy

37

Một ví dụ khác của phương pháp giải quyết vấn đề này :

def dist(x,y):   
    return numpy.sqrt(numpy.sum((x-y)**2))

a = numpy.array((xa,ya,za))
b = numpy.array((xb,yb,zb))
dist_a_b = dist(a,b)

1
bạn có thể sử dụng triển khai sqrt và / hoặc tổng của numpy không? Điều đó sẽ làm cho nó nhanh hơn (?).
u0b34a0f6ae

1
Tôi tìm thấy điều này ở phía bên kia của các interwebs norm = lambda x: N.sqrt(N.square(x).sum()); norm(x-y)
u0b34a0f6ae

2
gãi mà. nó phải ở đâu đó đây là:numpy.linalg.norm(x-y)
u0b34a0f6ae

13

Bắt đầu Python 3.8, mathmô-đun trực tiếp cung cấp disthàm, trả về khoảng cách euclide giữa hai điểm (được đưa ra dưới dạng bộ hoặc danh sách tọa độ):

from math import dist

dist((1, 2, 6), (-2, 3, 2)) # 5.0990195135927845

Và nếu bạn đang làm việc với danh sách:

dist([1, 2, 6], [-2, 3, 2]) # 5.0990195135927845

12

Nó có thể được thực hiện như sau. Tôi không biết nó nhanh như thế nào, nhưng nó không sử dụng NumPy.

from math import sqrt
a = (1, 2, 3) # Data point 1
b = (4, 5, 6) # Data point 2
print sqrt(sum( (a - b)**2 for a, b in zip(a, b)))

Làm toán trực tiếp trong python không phải là một ý tưởng hay vì python rất chậm, cụ thể for a, b in zip(a, b). Nhưng hữu ích không kém.
Sigex

10

Tôi tìm thấy chức năng 'dist' trong matplotlib.mlab, nhưng tôi không nghĩ nó đủ tiện dụng.

Tôi đang đăng nó ở đây chỉ để tham khảo.

import numpy as np
import matplotlib as plt

a = np.array([1, 2, 3])
b = np.array([2, 3, 4])

# Distance between a and b
dis = plt.mlab.dist(a, b)

Điều này không còn được áp dụng. (mpl 3.0)
Nico Schlömer

8

Tôi thích np.dot(chấm sản phẩm):

a = numpy.array((xa,ya,za))
b = numpy.array((xb,yb,zb))

distance = (np.dot(a-b,a-b))**.5

8

Một lớp lót đẹp:

dist = numpy.linalg.norm(a-b)

Tuy nhiên, nếu tốc độ là mối quan tâm tôi sẽ khuyên bạn nên thử nghiệm trên máy của mình. Tôi đã thấy rằng việc sử dụng maththư viện sqrtvới **toán tử cho hình vuông trên máy của tôi nhanh hơn nhiều so với giải pháp NumPy một lớp.

Tôi đã chạy thử nghiệm bằng chương trình đơn giản này:

#!/usr/bin/python
import math
import numpy
from random import uniform

def fastest_calc_dist(p1,p2):
    return math.sqrt((p2[0] - p1[0]) ** 2 +
                     (p2[1] - p1[1]) ** 2 +
                     (p2[2] - p1[2]) ** 2)

def math_calc_dist(p1,p2):
    return math.sqrt(math.pow((p2[0] - p1[0]), 2) +
                     math.pow((p2[1] - p1[1]), 2) +
                     math.pow((p2[2] - p1[2]), 2))

def numpy_calc_dist(p1,p2):
    return numpy.linalg.norm(numpy.array(p1)-numpy.array(p2))

TOTAL_LOCATIONS = 1000

p1 = dict()
p2 = dict()
for i in range(0, TOTAL_LOCATIONS):
    p1[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))
    p2[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))

total_dist = 0
for i in range(0, TOTAL_LOCATIONS):
    for j in range(0, TOTAL_LOCATIONS):
        dist = fastest_calc_dist(p1[i], p2[j]) #change this line for testing
        total_dist += dist

print total_dist

Trên máy của tôi, math_calc_distchạy nhanh hơn nhiều numpy_calc_dist: 1,5 giây so với 23,5 giây.

Để có được sự khác biệt có thể đo được giữa fastest_calc_distmath_calc_disttôi đã phải lên TOTAL_LOCATIONStới 6000. Sau đó fastest_calc_distmất ~ 50 giây trong khi math_calc_distmất ~ 60 giây.

Bạn cũng có thể thử nghiệm numpy.sqrtnumpy.squaremặc dù cả hai đều chậm hơn các mathlựa chọn thay thế trên máy của tôi.

Các thử nghiệm của tôi đã được chạy với Python 2.6.6.


48
Bạn đang hiểu sai về cách sử dụng numpy ... Đừng sử dụng các vòng lặp hoặc liệt kê các cách hiểu. Nếu bạn đang lặp đi lặp lại và áp dụng chức năng cho từng mục, thì, vâng, các chức năng numpy sẽ chậm hơn. Toàn bộ vấn đề là để vector hóa mọi thứ.
Joe Kington

Nếu tôi di chuyển cuộc gọi numpy.array vào vòng lặp nơi tôi đang tạo các điểm tôi sẽ nhận được kết quả tốt hơn với numpy_calc_dist, nhưng nó vẫn chậm hơn 10 lần so với quick_calc_dist. Nếu tôi có nhiều điểm đó và tôi cần tìm khoảng cách giữa mỗi cặp thì tôi không chắc mình có thể làm gì khác để tạo lợi thế cho numpy.
dùng118662

15
Tôi nhận ra chủ đề này đã cũ, nhưng tôi chỉ muốn củng cố những gì Joe nói. Bạn không sử dụng numpy chính xác. Những gì bạn đang tính là tổng khoảng cách từ mọi điểm trong p1 đến mọi điểm trong p2. Giải pháp với numpy / scipy nhanh hơn 70 lần trên máy của tôi. Biến p1 và p2 thành một mảng (thậm chí sử dụng một vòng lặp nếu bạn có chúng được định nghĩa là dicts). Sau đó, bạn có thể nhận được tổng số tiền trong một bước , scipy.spatial.distance.cdist(p1, p2).sum(). Thế là xong.
Scott B

3
Hoặc sử dụng numpy.linalg.norm(p1-p2).sum()để lấy tổng giữa mỗi điểm trong p1 và điểm tương ứng trong p2 (nghĩa là không phải mọi điểm trong p1 đến mọi điểm trong p2). Và nếu bạn muốn mọi điểm trong p1 đến mọi điểm trong p2 và không muốn sử dụng scipy như trong nhận xét trước đây của tôi, thì bạn có thể sử dụng np.apply_along_axis cùng với numpy.linalg.norm để làm điều đó nhanh hơn nhiều sau đó là giải pháp "nhanh nhất" của bạn.
Scott B

2
Các phiên bản trước của NumPy có triển khai định mức rất chậm. Trong các phiên bản hiện tại, không cần tất cả điều này.
Fred Foo

8

Bạn chỉ có thể trừ các vectơ và sau đó sản phẩm bên trong.

Theo gương của bạn,

a = numpy.array((xa, ya, za))
b = numpy.array((xb, yb, zb))

tmp = a - b
sum_squared = numpy.dot(tmp.T, tmp)
result = sqrt(sum_squared)

5
Điều này sẽ cho tôi hình vuông của khoảng cách. bạn đang thiếu một sqrt ở đây.
Nathan Fellman

6

abnhư bạn đã xác định chúng, bạn cũng có thể sử dụng:

distance = np.sqrt(np.sum((a-b)**2))

6

Với Python 3.8, nó rất dễ dàng.

https://docs.python.org/3/l Library / math.html # math.dist

math.dist(p, q)

Trả về khoảng cách Euclide giữa hai điểm p và q, mỗi điểm được đưa ra dưới dạng một chuỗi (hoặc có thể lặp lại) của tọa độ. Hai điểm phải có cùng chiều.

Khá tương đương với:

sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))


5

Đây là một số mã ngắn gọn cho khoảng cách Euclide trong Python với hai điểm được biểu thị dưới dạng danh sách trong Python.

def distance(v1,v2): 
    return sum([(x-y)**2 for (x,y) in zip(v1,v2)])**(0.5)

1
Numpy cũng chấp nhận các danh sách làm đầu vào (không cần phải vượt qua một mảng rõ ràng)
Alejandro Sazo

4

Kể từ Python 3,8

Vì Python 3.8, mathmô-đun bao gồm hàm math.dist().
Xem tại đây https://docs.python.org/3.8/l Library / math.html # math.dist .

math.dist (p1, p2)
Trả về khoảng cách Euclide giữa hai điểm p1 và p2, mỗi điểm được đưa ra dưới dạng một chuỗi (hoặc có thể lặp lại) của tọa độ.

import math
print( math.dist( (0,0),   (1,1)   )) # sqrt(2) -> 1.4142
print( math.dist( (0,0,0), (1,1,1) )) # sqrt(3) -> 1.7321

3

Tính khoảng cách Euclide cho không gian đa chiều:

 import math

 x = [1, 2, 6] 
 y = [-2, 3, 2]

 dist = math.sqrt(sum([(xi-yi)**2 for xi,yi in zip(x, y)]))
 5.0990195135927845

2
import numpy as np
from scipy.spatial import distance
input_arr = np.array([[0,3,0],[2,0,0],[0,1,3],[0,1,2],[-1,0,1],[1,1,1]]) 
test_case = np.array([0,0,0])
dst=[]
for i in range(0,6):
    temp = distance.euclidean(test_case,input_arr[i])
    dst.append(temp)
print(dst)

2
Sự khác biệt từ câu trả lời này là gì?
xskxzr


2

Bạn có thể dễ dàng sử dụng công thức

distance = np.sqrt(np.sum(np.square(a-b)))

điều này thực sự không có gì khác hơn là sử dụng định lý của Pythagoras để tính khoảng cách, bằng cách thêm các bình phương Δx, y và Δz và root kết quả.


1

Tìm sự khác biệt của hai ma trận đầu tiên. Sau đó, áp dụng phép nhân phần tử khôn ngoan với lệnh nhân của numpy. Sau đó, tìm tổng của phần tử ma trận mới nhân lên. Cuối cùng, tìm căn bậc hai của tổng.

def findEuclideanDistance(a, b):
    euclidean_distance = a - b
    euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
    euclidean_distance = np.sqrt(euclidean_distance)
    return euclidean_distance

1
import numpy as np
# any two python array as two points
a = [0, 0]
b = [3, 4]

Trước tiên, bạn thay đổi danh sách thành mảng numpy và làm như thế này : print(np.linalg.norm(np.array(a) - np.array(b))). Phương pháp thứ hai trực tiếp từ danh sách python như:print(np.linalg.norm(np.subtract(a,b)))

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.