2
votes

comment calculer la distance d'une trame de données par rapport à une autre trame de données?

disons que j'ai un bloc de données composé de points:

df1:

x   y    z  label
1.1 2.1 3.1   2
4.1 5.1 6.1   0
7.1 8.1 9.1   1

et j'ai aussi un autre bloc de données de points:

df2:

x  y  z   label
4  5  6    0
7  8  9    1
1  2  3    2

est-il quand même là pour parcourir df one et voir quel point est le plus proche de l'intérieur de df2 et remplacer l'étiquette par l'étiquette du point le plus proche de donc ..

le résultat que je voudrais:

x   y  z     label
1.1 2.1 3.1     2
4.1 5.1 6.1     1
7.1 8.1 9.1     0

merci d'avoir lu ma question!


3 commentaires

Définir le plus proche? Quelle est l'équation? Somme de la différence sur une ligne?


Je veux dire juste à partir d'une simple formule de distance. jusqu'ici le point d'instance (1,2,3) étant le placard du point (1.1,2.1,3.1)


BCOM, a-t-on répondu à cette question?


4 Réponses :


1
votes

Je ne peux penser qu'à la distance de scipy

from scipy.spatial import distance
df1['label']=df2.label.iloc[distance.cdist(df1.iloc[:,:-1], df2.iloc[:,:-1], metric='euclidean').argmin(1)].values
df1
Out[446]: 
     x    y    z  label
0  1.1  2.1  3.1      2
1  4.1  5.1  6.1      0
2  7.1  8.1  9.1      1


1 commentaires

Cela peut devenir coûteux en calcul. Vous voudrez peut-être implémenter un kd-tree si vous faites cela sur deux grands tableaux.



0
votes
SELECT ABS($df1 - $df2) as nearest, ...
FROM yourtable
ORDER BY nearest ASC
LIMIT 1
order them by 'X' index and then compare the $result arrays
this would look for the nearest number between the tables. https://www.w3schools.com/sql/func_sqlserver_abs.asp
the ABS function returns an absolute number so it will be a good solution as long as you have entire numbers on df2.hope it helps.

0 commentaires

2
votes

Voici une version utilisant kd-tree, qui peut être beaucoup plus rapide pour les grands ensembles de données.

fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(X[:,0],X[:,1],X[:,2])
ax.scatter(Y[:,0],Y[:,1],Y[:,2])
for i in range(len(X)): #plot each point + it's index as text above
    ax.text(X[i,0],X[i,1],X[i,2],  '%s' % (str(i)), size=20, zorder=1, color='blue') 
for i in range(len(Y)): #plot each point + it's index as text above
    ax.text(Y[i,0],Y[i,1],Y[i,2],  '%s' % (str(i)), size=20, zorder=1, color='orange') 

Voici une image que vous pouvez utiliser pour vérifier les résultats. Les points bleus sont des points x et l'orange sont des points y. entrez la description de l'image ici

voici le code du tracé, en utilisant matplotlib version 3.0.2

import numpy as np
import pandas as pd
from  sklearn.neighbors import KDTree
np.random.seed(0)
#since you have df1 and df2, you will want to convert the dfs to array here with
#X=df1['x'.'y','z'].to_numpy()
#Y=df2['x','y','z'].to_numpy()
X = np.random.random((10, 3))  # 10 points in 3 dimensions
Y = np.random.random((10, 3))
tree = KDTree(Y, leaf_size=2)  


#loop though the x array and find the closest point in y to each x  
#note the you can find as many as k nearest neighbors by this method
#though yours only calls for the k=1 case
dist, ind = tree.query(X, k=1) 

df1=pd.DataFrame(X, columns=['x','y','z']) 

#set the labels to the closest point to each neighbor
df1['label']=ind 

#this is cheesy, but it removes the list brackets 
#get rid of the following line if you want more than k=1 nearest neighbors
df1['label']=df1['label'].str.get(0).str.get(0)  
print(df1)

df1:
          x         y         z
0  0.548814  0.715189  0.602763
1  0.544883  0.423655  0.645894
2  0.437587  0.891773  0.963663
3  0.383442  0.791725  0.528895
4  0.568045  0.925597  0.071036
5  0.087129  0.020218  0.832620
6  0.778157  0.870012  0.978618
7  0.799159  0.461479  0.780529
8  0.118274  0.639921  0.143353
9  0.944669  0.521848  0.414662
df2:
          x         y         z
0  0.264556  0.774234  0.456150
1  0.568434  0.018790  0.617635
2  0.612096  0.616934  0.943748
3  0.681820  0.359508  0.437032
4  0.697631  0.060225  0.666767
5  0.670638  0.210383  0.128926
6  0.315428  0.363711  0.570197
7  0.438602  0.988374  0.102045
8  0.208877  0.161310  0.653108
9  0.253292  0.466311  0.244426

Out:
          x         y         z  label
0  0.548814  0.715189  0.602763      0
1  0.544883  0.423655  0.645894      6
2  0.437587  0.891773  0.963663      2
3  0.383442  0.791725  0.528895      0
4  0.568045  0.925597  0.071036      7
5  0.087129  0.020218  0.832620      8
6  0.778157  0.870012  0.978618      2
7  0.799159  0.461479  0.780529      2
8  0.118274  0.639921  0.143353      9
9  0.944669  0.521848  0.414662      3


7 commentaires

si j'avais des points 11-d, mon cas serait-il toujours k = 1? parce que j'obtiens une "dimension de données de requête doit correspondre à la dimension de données d'entraînement"


Pouvez-vous poster un exemple + l'erreur? k devrait être 1 si vous ne voulez que le voisin le plus proche, et le 11-d n'effectue pas cela. Il s'agit simplement du nombre de voisins que vous souhaitez renvoyer pour chaque point. Si vous alimentez la requête en un seul point, il vous suffit de la remodeler. Disons que je veux juste regarder le plus proche voisin du premier point de X. Ensuite, vous remodelez comme suit "dist, ind = tree.query (X [0,:]. Reshape (1, -1), k = 1 ). " kd-tree devrait fonctionner avec n'importe quel nombre de dimensions euclidiennes.


Je viens de tester mon code avec un espace 11-d et cela fonctionne, mais vous devez vous débarrasser de tout après cette ligne "dist, ind = tree.query (X, k = 1)" car les pandas et le traçage des parties du code ont été écrits en supposant un espace 3D. Évidemment, vous ne pouvez pas tracer un espace 11-d de manière facile à comprendre, par exemple, bien que vous puissiez prendre des coupes transversales.


quand vous dites se débarrasser de tout après cette ligne, comment puis-je encore présenter les nouvelles étiquettes alors?


parce que si je me débarrasse de tout après ça, j'ai juste l'arbre des données et c'est tout, désolé d'essayer de comprendre


J'ajouterais quelque chose pour le cas 11-j


J'ai posté une autre réponse pour le cas généralisé. Je pense que cet article répond mieux à votre question postée, et si c'était moi, j'accepterais cela comme réponse à la question posée.



0
votes

Ma première réponse répond à la question posée, mais le PO voulait une solution généralisée pour n'importe quel nombre de dimensions, pas seulement trois.

import numpy as np
import pandas as pd
from  sklearn.neighbors import KDTree


np.random.seed(0)
#since you have df1 and df2, you will want to convert the dfs to array here with
#X=df1['x'.'y','z'].to_numpy()
#Y=df2['x','y','z'.to_numpy()
n=11    #n=number of dimensions in your sample
X = np.random.random((10, n))  # 10 points in n dimensions
Y = np.random.random((10, n))
tree = KDTree(Y, leaf_size=2)  

indices=[]
#for i in range(len(X)):
    #loop though the x array and find the closest point in y to each x       
dist, ind = tree.query(X, k=1) 
#indices.append(ind)     
df1=pd.DataFrame(X)  
##set the labels to the closest point to each neighbor
df1['label']=ind 

Le résultat que vous voulez est maintenant dans df1, mais vous ne pouvez pas le tracer facilement ou l'interpréter sans avoir un cerveau fou. Preuve de succès basée sur la version 3D également publiée ici.


0 commentaires