Je viens de commencer à utiliser scipy/numpy. J'ai un tableau 100000 * 3, chaque ligne est une coordonnée et un point central 1 * 3. Je veux calculer la distance pour chaque ligne du tableau au centre et les stocker dans un autre tableau. Quel est le moyen le plus efficace de le faire?
Je voudrais jeter un oeil à scipy.spatial.distance.cdist
:
http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cdist.html
import numpy as np
import scipy
a = np.random.normal(size=(10,3))
b = np.random.normal(size=(1,3))
dist = scipy.spatial.distance.cdist(a,b) # pick the appropriate distance metric
dist
pour la métrique distante par défaut est équivalent à:
np.sqrt(np.sum((a-b)**2,axis=1))
bien que cdist
soit beaucoup plus efficace pour les baies de grande taille (sur ma machine, pour votre problème de taille, cdist
est plus rapide d'un facteur environ 35 fois).
Je voudrais utiliser la mise en œuvre de Sklearn de la distance euclidienne. L'avantage est l'utilisation de l'expression la plus efficace en utilisant la multiplication Matrix:
dist(x, y) = sqrt(dot(x, x) - 2 * dot(x, y) + dot(y, y)
Un script simple ressemblerait à ceci:
import numpy as np
x = np.random.Rand(1000, 3)
y = np.random.Rand(1000, 3)
dist = np.sqrt(np.dot(x, x)) - (dot(x, y) + dot(x, y)) + dot(y, y)
Les avantages de cette approche ont été décrits avec précision dans la documentation de sklearn: http://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.euclidean_distances.html#sklearn.metrics .pairwise.euclidean_distances
J'utilise cette approche pour traiter des données volumineuses volumineuses (10000, 10000) avec quelques modifications mineures, telles que l'utilisation de la fonction np.einsum.
Vous pouvez également utiliser le développement de la norme (similaire aux identités remarquables). C'est probablement le moyen le plus efficace de calculer la distance d'une matrice de points.
Voici un extrait de code que j'ai utilisé à l'origine pour une implémentation de k-Nearest-Neighbours, dans Octave, mais vous pouvez facilement l'adapter à numpy puisqu'il utilise uniquement des multiplications de matrice (l'équivalent est numpy.dot ()):
% Computing the euclidian distance between each known point (Xapp) and unknown points (Xtest)
% Note: we use the development of the norm just like a remarkable identity:
% ||x1 - x2||^2 = ||x1||^2 + ||x2||^2 - 2*<x1,x2>
[napp, d] = size(Xapp);
[ntest, d] = size(Xtest);
A = sum(Xapp.^2, 2);
A = repmat(A, 1, ntest);
B = sum(Xtest.^2, 2);
B = repmat(B', napp, 1);
C = Xapp*Xtest';
dist = A+B-2.*C;
Vous devrez peut-être spécifier de manière plus détaillée la fonction de distance qui vous intéresse, mais voici une implémentation très simple (et efficace) de Squared Euclidean Distance basée sur inner product
(qui peut évidemment être généralisée, de manière simple, autre type de mesure de distance):
In []: P, c= randn(5, 3), randn(1, 3)
In []: dot(((P- c)** 2), ones(3))
Out[]: array([ 8.80512, 4.61693, 2.6002, 3.3293, 12.41800])
Où P
sont vos points et c
est le centre.
#is it true, to find the biggest distance between the points in surface?
from math import sqrt
n = int(input( "enter the range : "))
x = list(map(float,input("type x coordinates: ").split()))
y = list(map(float,input("type y coordinates: ").split()))
maxdis = 0
for i in range(n):
for j in range(n):
print(i, j, x[i], x[j], y[i], y[j])
dist = sqrt((x[j]-x[i])**2+(y[j]-y[i])**2)
if maxdis < dist:
maxdis = dist
print(" maximum distance is : {:5g}".format(maxdis))
Cela pourrait ne pas répondre directement à votre question, mais si vous êtes après toutes les permutations de paires de particules, j'ai trouvé la solution suivante plus rapide que la fonction pdist dans certains cas.
import numpy as np
L = 100 # simulation box dimension
N = 100 # Number of particles
dim = 2 # Dimensions
# Generate random positions of particles
r = (np.random.random(size=(N,dim))-0.5)*L
# uti is a list of two (1-D) numpy arrays
# containing the indices of the upper triangular matrix
uti = np.triu_indices(100,k=1) # k=1 eliminates diagonal indices
# uti[0] is i, and uti[1] is j from the previous example
dr = r[uti[0]] - r[uti[1]] # computes differences between particle positions
D = np.sqrt(np.sum(dr*dr, axis=1)) # computes distances; D is a 4950 x 1 np array
Voir this pour un regard plus en profondeur sur ce sujet, sur mon blog.