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!
4 Réponses :
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
Cela peut devenir coûteux en calcul. Vous voudrez peut-être implémenter un kd-tree si vous faites cela sur deux grands tableaux.
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.
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.
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
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.
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.
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?