J'ai 2 géodonnées:
import geopandas as gpd
from shapely.geometry import Point
gpd1 = gpd.GeoDataFrame([['John',1,Point(1,1)],['Smith',1,Point(2,2)],['Soap',1,Point(0,2)]],columns=['Name','ID','geometry'])
gpd2 = gpd.GeoDataFrame([['Work',Point(0,1.1)],['Shops',Point(2.5,2)],['Home',Point(1,1.1)]],columns=['Place','geometry'])
et je veux trouver le nom du point le plus proche dans gpd2 pour chaque ligne dans gpd1:
desired_output =
Name ID geometry Nearest
0 John 1 POINT (1 1) Home
1 Smith 1 POINT (2 2) Shops
2 Soap 1 POINT (0 2) Work
J'ai essayé de faire fonctionner cela en utilisant une fonction lambda:
gpd1['Nearest'] = gpd1.apply(lambda row: min_dist(row.geometry,gpd2)['Place'] , axis=1)
avec
def min_dist(point, gpd2):
geoseries = some_function()
return geoseries
Réponses:
Vous pouvez utiliser directement la fonction Shapely Points les plus proches (les géométries des GeoSeries sont des géométries Shapely):
Explication
la source
sample_point = gpd2.geometry.unary_union[400] /
sample_point in gpd2.geometry
Cela renvoie True.gpd2.geometry == sample_point
Cela sort tout faux.gpd2.geometry.geom_equals(sample_point)
fonctionne.Si vous avez de grandes trames de données, j'ai trouvé que
scipy
c'est l'indice spatial cKDTree.query
renvoie des résultats très rapides pour les recherches de voisins les plus proches. Comme il utilise un index spatial, ses ordres de grandeur sont plus rapides que de parcourir la trame de données et de trouver ensuite le minimum de toutes les distances. C'est aussi plus rapide que d'utiliser des galbéesnearest_points
galbées avec RTree (la méthode d'index spatial disponible via les géopandas) car cKDTree vous permet de vectoriser votre recherche alors que l'autre méthode ne le fait pas.Voici une fonction d'assistance qui renverra la distance et le «nom» du plus proche voisin à
gpd2
partir de chaque pointgpd1
. Cela suppose que les deux gdfs ont unegeometry
colonne (de points).Et si vous souhaitez trouver le point le plus proche d'une ligne de chaîne, voici un exemple de travail complet:
la source
Deviner:
Bien sûr, certaines critiques sont les bienvenues. Je ne suis pas fan du recalcul de gpd2 ['Dist'] pour chaque ligne de gpd1 ...
la source
La réponse de Gene n'a pas fonctionné pour moi. Enfin, j'ai découvert que gpd2.geometry.unary_union avait pour résultat une géométrie qui ne contenait qu'environ 30 000 de mon total d'environ 150 000 points. Pour toute autre personne rencontrant le même problème, voici comment je l'ai résolu:
la source
Pour quiconque ayant des erreurs d'indexation avec ses propres données lors de l'utilisation de l' excellente réponse de @ JHuw , mon problème était que mes index ne s'alignaient pas. Réinitialiser l'index de gdfA et gdfB a résolu mes problèmes, cela peut peut-être aussi vous aider @ Shakedk .
la source