Tengo 2 geodataframes:
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'])
y quiero encontrar el nombre del punto más cercano en gpd2 para cada fila en 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
He estado tratando de hacer que esto funcione usando una función lambda:
gpd1['Nearest'] = gpd1.apply(lambda row: min_dist(row.geometry,gpd2)['Place'] , axis=1)
con
def min_dist(point, gpd2):
geoseries = some_function()
return geoseries
Respuestas:
Puede usar directamente la función Shapely Puntos más cercanos (las geometrías de GeoSeries son geometrías Shapely):
Explicación
fuente
sample_point = gpd2.geometry.unary_union[400] /
sample_point in gpd2.geometry
Esto devuelve True.gpd2.geometry == sample_point
Esto sale todo falso.gpd2.geometry.geom_equals(sample_point)
obras.Si tiene grandes marcos de datos, he descubierto que
scipy
el.query
método de índice espacial cKDTree devuelve resultados muy rápidos para las búsquedas de vecinos más cercanos. Como utiliza un índice espacial, es de órdenes de magnitud más rápido que recorrer el marco de datos y luego encontrar el mínimo de todas las distancias. También es más rápido que usarnearest_points
Shapely 's con RTree (el método de índice espacial disponible a través de geopandas) porque cKDTree le permite vectorizar su búsqueda, mientras que el otro método no.Aquí hay una función auxiliar que devolverá la distancia y el 'Nombre' del vecino más cercano
gpd2
desde cada puntogpd1
. Se supone que ambos gdfs tienen unageometry
columna (de puntos).Y si desea encontrar el punto más cercano a LineString, aquí hay un ejemplo de trabajo completo:
fuente
Lo averigué:
Por supuesto, algunas críticas son bienvenidas. No soy fanático de volver a calcular gpd2 ['Dist'] para cada fila de gpd1 ...
fuente
La respuesta de Gene no funcionó para mí. Finalmente descubrí que gpd2.geometry.unary_union resultó en una geometría que solo contenía aproximadamente 30,000 de mi total de aproximadamente 150,000 puntos. Para cualquier otra persona que tenga el mismo problema, así es como lo resolví:
fuente
Para cualquiera que tenga errores de indexación con sus propios datos mientras usa la excelente respuesta de @ JHuw , mi problema fue que mis índices no se alinearon. Restablecer el índice de gdfA y gdfB resolvió mis problemas, tal vez esto también pueda ayudarlo @ Shakedk .
fuente