यूक्लिडियन दूरी की गणना NumPy के साथ कैसे की जा सकती है?


529

मेरे 3 डी में दो अंक हैं:

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

और मैं दूरी की गणना करना चाहता हूं:

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

NumPy के साथ, या सामान्य रूप से पायथन के साथ ऐसा करने का सबसे अच्छा तरीका क्या है? मेरे पास है:

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

जवाबों:


883

उपयोग करें numpy.linalg.norm:

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

डेटा माइनिंग के इंट्रोडक्शन में आप इसके पीछे की थ्योरी पा सकते हैं

यह काम करता है क्योंकि इयूक्लिडियन दूरी है l2 आदर्श और का डिफ़ॉल्ट मान ord numpy.linalg.norm में पैरामीटर 2 है।

यहाँ छवि विवरण दर्ज करें


13
Linalg.norm डॉक्स यहां देखे जा सकते हैं: docs.scipy.org/doc/numpy/reference/generated/… मेरी एकमात्र वास्तविक टिप्पणी एक मानक के बीच संबंध को इंगित करने की तरह थी (इस मामले में फ्रोबेनियस मानदंड / 2-मानक जो आदर्श कार्य के लिए डिफ़ॉल्ट है) और एक मीट्रिक (इस मामले में यूक्लिडियन दूरी)।
मार्क लविन

7
अगर ओपी निर्देशांक की एक सरणी के बीच की दूरी की गणना करना चाहता था तो scipy.spatial.distance.cdist का उपयोग करना भी संभव है ।
mnky9800n

2
मेरा प्रश्न है: इसके विपरीत इसका उपयोग क्यों करें? stackoverflow.com/a/21986532/189411 से scipy.spatial आयात दूरी a = (1,2,3) b = (4,5,6) dst = दूरी.euclidean (a, b)
डोमेनाटा मोनाको

2
SciPy के cdist फ़ंक्शन के लिए लिंक अपडेट किया गया: docs.scipy.org/doc/scipy/reference/generated/…
Steven C. Howell

numpy.linalg.norm की तुलना में और भी तेज़ विधियाँ हैं: semantive.com/blog/…
मुहम्मद

161

SciPy में इसके लिए एक फंक्शन है। इसे यूक्लिडियन कहा जाता है ।

उदाहरण:

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

56
यदि आप दक्षता की तलाश करते हैं तो सुन्न कार्य का उपयोग करना बेहतर होता है। Scipy दूरी numpy.linalg.norm (ab) (और numpy.sqrt (numpy.sum (ab) ** 2)) के रूप में दोगुनी धीमी है। मेरी मशीन पर मुझे स्किपी (v0.15.1) के साथ 19.7 19 और संख्यात्मक के साथ 8.9 pys मिलते हैं (v1.9.2)। कई मामलों में एक प्रासंगिक अंतर नहीं है लेकिन अगर लूप अधिक महत्वपूर्ण हो सकता है। तेज़ कोड पर एक त्वरित नज़र से यह धीमा प्रतीत होता है क्योंकि यह दूरी की गणना करने से पहले सरणी को मान्य करता है।
अल्गोल्ड

@ माइकलाइमाइस हां, स्कैपी फ़ंक्शन पूरी तरह से सुन्न के साथ संगत हैं। लेकिन एक नज़र यहाँ क्या सुझाव दिया है (जो भी सुन्न सरणी पर काम करता है, निश्चित रूप से)
एविज़न

@ संशोधन सुनिश्चित नहीं है कि यह मेरे लिए काम करेगा क्योंकि मेरे मैट्रिस में अलग-अलग पंक्तियों की संख्या है; एक मैट्रिक्स काम नहीं करने के लिए उन्हें घटाना करने की कोशिश कर रहा है
Bjorks नंबर एक प्रशंसक

@ माइकलाइफमाइस क्या आप वास्तव में इन दो मैट्रिसेस के साथ गणना करने की कोशिश कर रहे हैं? अपेक्षित इनपुट / आउटपुट क्या है?
Avision

पीछा करने के लिए ty। यहाँ एक विवरण है : ysts.stackexchange.com/questions/322620/… । मेरे पास 'संचालन' की 2 तालिकाएँ हैं; प्रत्येक में एक 'कोड' लेबल होता है, लेकिन लेबल के दो सेट बिलकुल अलग होते हैं। मेरा लक्ष्य पहले में एक निश्चित कोड के अनुरूप दूसरी तालिका से सबसे अच्छा या निकटतम कोड ढूंढना है (मुझे पता है कि मैनुअल निरीक्षण से उत्तर क्या होना चाहिए, लेकिन बाद में सैकड़ों तालिकाओं को स्केल करना चाहते हैं)। तो पहला सबसेट तय है; मैं
एवी यूक्लिड डिस्टर्ब

108

एक बार में कई दूरियों की गणना करने के इच्छुक लोगों के लिए, मैंने परफ्लोट (मेरी एक छोटी परियोजना) का उपयोग करके थोड़ी तुलना की है।

पहली सलाह यह है कि अपने डेटा को व्यवस्थित करें ताकि सरणियों का आयाम हो (3, n)(और स्पष्ट रूप से सी-सन्निहित हैं)। जोड़ने सन्निहित पहले आयाम में होता है, चीजें तेजी से कर रहे हैं, और यह नहीं बात बहुत ज्यादा है, तो आप का उपयोग करता है sqrt-sumके साथ axis=0, linalg.normके साथ axis=0, या

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

जो कि मामूली अंतर से सबसे तेज संस्करण है। (यह वास्तव में सिर्फ एक पंक्ति के लिए भी सच है)

वे वेरिएंट जहां आप दूसरी धुरी पर योग करते axis=1हैं, सभी काफी धीमे हैं।

यहाँ छवि विवरण दर्ज करें


प्लॉट को फिर से तैयार करने के लिए कोड:

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
धन्यवाद। मैंने आज कुछ नया सीखा! एकल आयाम सरणी के लिए, स्ट्रिंग होगाi,i->
तीर्थ R

4
अगर यह स्मृति की खपत की तुलना में अधिक है तो itd और अधिक ठंडा हो सकता है
ड्रैगनलाज़

मैं आपके कोड का उपयोग करना चाहूंगा लेकिन मैं यह समझने में संघर्ष कर रहा हूं कि डेटा को कैसे व्यवस्थित किया जाना चाहिए। क्या आप एक उदाहरण दे सकते हैं? कैसा dataदिखता है?
जोहान्स वेसनर

1
वास्तव में स्वच्छ परियोजना और निष्कर्ष। मैं उसी प्रकृति के कुछ आधे-अधूरे एड एड कर रहा हूं, इसलिए मुझे लगता है कि मैं आपके प्रोजेक्ट में बदल जाऊंगा और यदि आप उनके साथ हैं तो मतभेदों में योगदान कर सकते हैं।
मैड फिजिसिस्ट

42

मैं विभिन्न प्रदर्शन नोट्स के साथ सरल उत्तर पर विस्तार करना चाहता हूं। np.linalg.norm आपकी आवश्यकता से अधिक शायद करेगा:

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

सबसे पहले - यह फ़ंक्शन एक सूची पर काम करने और सभी मानों को वापस करने के लिए डिज़ाइन किया गया है, उदाहरण के लिए pAबिंदुओं के सेट से दूरी की तुलना करने के लिए sP:

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

कई बातें याद रखें:

  • पायथन फ़ंक्शन कॉल महंगे हैं।
  • [नियमित] पायथन नाम लुक्स को कैश नहीं करता है।

इसलिए

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

यह दिखने में उतना मासूम नहीं है।

>>> 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

सबसे पहले - हर बार जब हम इसे कॉल करते हैं, तो हमें "एनपी" के लिए एक ग्लोबल लुकअप करना पड़ता है, "लिनलैग" के लिए एक स्कोप्ड लुकअप और "नॉर्थ" के लिए एक स्कॉप्ड लुकअप, और केवल फंक्शन को कॉल करने के ओवरहेड दर्जनों अजगर के बराबर हो सकता है निर्देश।

अंत में, हमने परिणाम को स्टोर करने और वापसी के लिए इसे फिर से लोड करने के लिए दो ऑपरेशन बर्बाद किए ...

पहले सुधार पर पास: लुकअप को तेज़ करें, स्टोर को छोड़ें

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

हम कहीं अधिक सुव्यवस्थित हैं:

>>> 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

फ़ंक्शन कॉल ओवरहेड अभी भी कुछ काम करने के लिए, हालांकि। और आप यह निर्धारित करने के लिए मानदंड करना चाहेंगे कि क्या आप स्वयं गणित को बेहतर कर सकते हैं:

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

कुछ प्लेटफार्मों पर, **0.5की तुलना में तेज है math.sqrt। आपकी माइलेज भिन्न हो सकती है।

**** उन्नत प्रदर्शन नोट्स।

आप दूरी की गणना क्यों कर रहे हैं? यदि एकमात्र उद्देश्य इसे प्रदर्शित करना है,

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

के साथ कदम। लेकिन अगर आप दूरी की तुलना कर रहे हैं, रेंज चेक आदि कर रहे हैं, तो मैं कुछ उपयोगी प्रदर्शन टिप्पणियों को जोड़ना चाहूंगा।

आइए, दो मामलों को लें: किसी सूची में दूरी के आधार पर छँटाई या किसी सीमा में कमी को पूरा करने वाली वस्तुओं की सूची बनाना।

# 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)

पहली चीज़ जो हमें याद रखने की ज़रूरत है कि हम दूरी की गणना करने के लिए पाइथागोरस का उपयोग कर रहे हैं ( dist = sqrt(x^2 + y^2 + z^2)) इसलिए हम बहुत अधिक sqrtकॉल कर रहे हैं। गणित 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

संक्षेप में: जब तक हमें वास्तव में एक्स ^ 2 के बजाय एक्स की एक इकाई में दूरी की आवश्यकता होती है, हम गणना के सबसे कठिन हिस्से को समाप्त कर सकते हैं।

# 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)

महान, दोनों कार्य अब कोई महंगा वर्गमूल नहीं करते हैं। यह बहुत तेज हो जाएगा। हम इसे जनरेटर में परिवर्तित करके in_range को भी सुधार सकते हैं:

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

यह विशेष रूप से लाभ है अगर आप कुछ कर रहे हैं जैसे:

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

लेकिन अगर आप अगली चीज़ जो करने जा रहे हैं, उसके लिए एक दूरी की आवश्यकता होती है,

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

पैदावार tuples पर विचार करें:

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)

यह विशेष रूप से उपयोगी हो सकता है यदि आप श्रृंखला रेंज जांच कर सकते हैं ('ऐसी चीजें खोजें जो एक्स के पास हैं और एन के वाई के भीतर हैं', क्योंकि आपको फिर से दूरी की गणना नहीं करनी है)।

लेकिन क्या होगा यदि हम वास्तव में बड़ी सूची खोज रहे हैं thingsऔर हम उनमें से बहुत से लोगों के प्रत्याशित होने का अनुमान लगा रहे हैं?

वास्तव में एक बहुत ही सरल अनुकूलन है:

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

यह उपयोगी है या नहीं यह 'चीजों' के आकार पर निर्भर करेगा।

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 ...

और फिर, dist_sq उपज पर विचार करें। हमारा हॉटडॉग उदाहरण तब बनता है:

# 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
सुन्न करने के लिए इस तरह के एक अनुकूलित फ़ंक्शन को क्यों नहीं जोड़ें? पांडा के लिए एक विस्तार भी इस stackoverflow.com/questions/47643952/…
कीथ

3
मैंने दूरी के लिए आपका पहला गणितीय दृष्टिकोण संपादित किया। आप एक का उपयोग कर रहे थे pointZजो मौजूद नहीं था। मुझे लगता है कि आपका क्या मतलब था तीन आयामी अंतरिक्ष में दो बिंदु थे और मैंने तदनुसार संपादित किया। अगर मैं गलत था, तो कृपया मुझे बताएं।
ब्रैम वानरो

37

इस समस्या को हल करने की विधि का एक और उदाहरण :

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
क्या आप numpy का sqrt और / या योग कार्यान्वयन का उपयोग कर सकते हैं? इसे तेज (?) करना चाहिए।
u0b34a0f6ae 20

1
मुझे यह इंटरव्यू के दूसरी तरफ मिला norm = lambda x: N.sqrt(N.square(x).sum()); norm(x-y)
u0b34a0f6ae 20

2
उसको खरोंचो। यह कहीं होना था। यहाँ यह है:numpy.linalg.norm(x-y)
u0b34a0f6ae

13

शुरू करना Python 3.8, mathमॉड्यूल सीधे distफ़ंक्शन प्रदान करता है , जो दो बिंदुओं के बीच यूक्लिडियन दूरी देता है (निर्देशांक के रूप में ट्यूपल्स या सूचियों के रूप में दिया गया है):

from math import dist

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

और अगर आप सूचियों के साथ काम कर रहे हैं:

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

12

इसे निम्न की तरह किया जा सकता है। मुझे नहीं पता कि यह कितना तेज़ है, लेकिन यह 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)))

अजगर में सीधे गणित करना एक अच्छा विचार नहीं है क्योंकि विशेष रूप से अजगर बहुत धीमा है for a, b in zip(a, b)। लेकिन उपयोगी कोई भी कम नहीं है।
सिगेक्स

10

मुझे matplotlib.mlab में एक 'dist' फ़ंक्शन मिलता है, लेकिन मुझे नहीं लगता कि यह पर्याप्त काम है।

मैं इसे यहाँ सिर्फ संदर्भ के लिए पोस्ट कर रहा हूँ।

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)

यह अब लागू नहीं है। (mpl 3.0)
निको श्लोमर

8

मुझे पसंद है np.dot(डॉट उत्पाद):

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

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

8

एक अच्छा एक लाइनर:

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

हालाँकि, अगर गति एक चिंता का विषय है तो मैं आपकी मशीन पर प्रयोग करने की सलाह दूंगा। मैंने पाया है कि वर्ग के लिए ऑपरेटर mathके sqrtसाथ पुस्तकालय का उपयोग **करना एक-लाइनर न्यूमपी समाधान की तुलना में मेरी मशीन पर बहुत तेज है।

मैंने इस सरल कार्यक्रम का उपयोग करके अपने परीक्षण चलाए:

#!/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

मेरी मशीन पर, 1.5 सेकंड बनाम 23.5 सेकंड की तुलना में math_calc_distबहुत तेज चलता है numpy_calc_dist

के बीच एक औसत दर्जे का अंतर पाने के लिए fastest_calc_distऔर math_calc_distमुझे TOTAL_LOCATIONS६००० तक का समय लेना पड़ा । फिर ~ ६० सेकंड लगते हैं fastest_calc_distजबकि math_calc_dist~ ६० सेकंड लगते हैं।

तुम भी प्रयोग कर सकते हैं numpy.sqrtऔर numpy.squareयद्यपि दोनों mathमेरी मशीन पर विकल्पों की तुलना में धीमा थे ।

मेरे परीक्षण पायथन 2.6.6 के साथ चलाए गए थे।


48
आप बुरी तरह से गलत समझ रहे हैं कि सुन्न का उपयोग कैसे करें ... छोरों या सूची समझ का उपयोग करें। यदि आप फ़ंक्शन के माध्यम से पुनरावृत्ति कर रहे हैं, और प्रत्येक आइटम के लिए फ़ंक्शन लागू कर रहे हैं , तो, हाँ, सुन्न कार्य धीमा हो जाएगा। पूरे बिंदु चीजों को वेक्टर करना है।
जो किंग्सटन

यदि मैं numpy.array कॉल को लूप में स्थानांतरित करता हूं, जहां मैं उन बिंदुओं का निर्माण कर रहा हूं जो मुझे numpy_calc_dist के साथ बेहतर परिणाम मिलते हैं, लेकिन यह अभी भी सबसे तेज_calc_dist की तुलना में 10x धीमा है। अगर मेरे पास कई बिंदु हैं और मुझे प्रत्येक जोड़ी के बीच की दूरी का पता लगाने की आवश्यकता है, तो मुझे यकीन नहीं है कि मैं और क्या फायदा उठाने के लिए कर सकता हूं।
user118662

15
मुझे एहसास हुआ कि यह धागा पुराना है, लेकिन मैं सिर्फ यह कहना चाहता हूं कि जो ने कहा था उसे फिर से मजबूत करना चाहिए। आप सही ढंग से सुन्न का उपयोग नहीं कर रहे हैं। आप जो गणना कर रहे हैं वह पी 2 में हर बिंदु से पी 2 तक की दूरी का योग है। मेरे मशीन पर 70 से अधिक बार सुपाच्य / घिसा हुआ घोल तेजी से निकलता है। पी 1 और पी 2 को एक सरणी में बनाएं (यहां तक ​​कि लूप का उपयोग करने पर भी यदि आपने उन्हें डिक्सेस के रूप में परिभाषित किया है)। तो फिर तुम, एक ही चरण में कुल योग प्राप्त कर सकते हैं scipy.spatial.distance.cdist(p1, p2).sum()। बस इतना ही।
स्कॉट बी

3
या numpy.linalg.norm(p1-p2).sum()पी 2 में प्रत्येक बिंदु और पी 2 में संबंधित बिंदु के बीच राशि प्राप्त करने के लिए उपयोग करें (यानी पी 2 में हर बिंदु पी 2 में हर बिंदु पर नहीं)। और यदि आप पी 2 में हर बिंदु को पी 2 में हर बिंदु पर चाहते हैं और मेरी पिछली टिप्पणी के अनुसार स्काइप का उपयोग नहीं करना चाहते हैं, तो आप np.apply_along_axis के साथ numpy.linalg.norm का उपयोग कर सकते हैं, फिर भी इसे बहुत, बहुत जल्दी। फिर आपका "सबसे तेज़" समाधान।
स्कॉट बी

2
NumPy के पिछले संस्करणों में बहुत धीमी गति से कार्यान्वयन था। वर्तमान संस्करणों में, इस सब की कोई आवश्यकता नहीं है।
फ्रेड फू

8

आप बस वैक्टर और फिर इनप्रोडक्ट को घटा सकते हैं।

अपने उदाहरण के बाद,

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
यह मुझे दूरी का वर्ग देगा। आप यहाँ एक sqrt याद कर रहे हैं।
नाथन फेलमैन


6

पायथन 3.8 के साथ, यह बहुत आसान है।

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

math.dist(p, q)

दो बिंदुओं p और q के बीच यूक्लिडियन दूरी लौटें, प्रत्येक निर्देशांक के अनुक्रम (या पुनरावृत्ति) के रूप में दिया गया है। दोनों बिंदुओं का आयाम समान होना चाहिए।

इसके बराबर:

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


5

यहाँ पायथन में यूक्लिडियन दूरी के लिए कुछ संक्षिप्त कोड दिए गए हैं जो पायथन में सूचियों के रूप में प्रतिनिधित्व करते हैं।

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

1
Numpy भी इनपुट के रूप में सूचियों को स्वीकार करता है (स्पष्ट रूप से एक सुन्न सरणी पास करने की आवश्यकता नहीं)
एलेजांद्रो

4

पायथन 3.8 के बाद से

पायथन 3.8 के बाद से mathमॉड्यूल में फ़ंक्शन शामिल है math.dist()
यहां देखें https://docs.python.org/3.8/library/math.html#math.dist

math.dist (p1, P2)
दो बिंदुओं p1 और P2 के बीच यूक्लिडियन दूरी लौटें, प्रत्येक निर्देशांक के अनुक्रम (या पुनरावृत्ति) के रूप में दिया गया है।

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

बहुआयामी अंतरिक्ष के लिए यूक्लिडियन दूरी की गणना करें:

 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
इस उत्तर से क्या फर्क पड़ता है ?
xskxzr


2

आप आसानी से सूत्र का उपयोग कर सकते हैं

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

जो वास्तव में hax, Δy और andz के वर्गों को जोड़कर और परिणाम को रूट करने के लिए दूरी की गणना करने के लिए पाइथागोरस के प्रमेय का उपयोग करने से ज्यादा कुछ नहीं करता है।


1

पहले दो मैट्रिक्स का अंतर ज्ञात करें। फिर, numpy के गुणा कमांड के साथ तत्व वार गुणा लागू करें। उसके बाद, तत्व बुद्धिमान गुणा नए मैट्रिक्स का योग खोजें। अंत में, सारांश का वर्गमूल ज्ञात कीजिए।

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]

आप पहले सूची को सुन्न सरणी में बदलें और इस तरह करें print(np.linalg.norm(np.array(a) - np.array(b))):। अजगर की सूची से सीधे दूसरी विधि इस प्रकार है:print(np.linalg.norm(np.subtract(a,b)))

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.