Estoy usando el siguiente código para encontrar un país (y, a veces, un estado) para millones de puntos GPS. El código actualmente toma aproximadamente un segundo por punto, que es increíblemente lento. El archivo de forma es de 6 MB.
Leí que las geopandas usan rtrees para uniones espaciales, lo que las hace increíblemente eficientes, pero esto no parece funcionar aquí. ¿Qué estoy haciendo mal? Esperaba mil puntos por segundo más o menos.
El archivo de forma y el csv se pueden descargar aquí (5 MB): https://www.dropbox.com/s/gdkxtpqupj0sidm/SpatialJoin.zip?dl=0
import pandas as pd
import geopandas as gpd
from geopandas import GeoDataFrame, read_file
from geopandas.tools import sjoin
from shapely.geometry import Point, mapping,shape
import time
#parameters
shapefile="K:/.../Shapefiles/Used/World.shp"
df=pd.read_csv("K:/.../output2.csv",index_col=None,nrows=20)# Limit to 20 rows for testing
if __name__=="__main__":
start=time.time()
df['geometry'] = df.apply(lambda z: Point(z.Longitude, z.Latitude), axis=1)
PointsGeodataframe = gpd.GeoDataFrame(df)
PolygonsGeodataframe = gpd.GeoDataFrame.from_file(shapefile)
PointsGeodataframe.crs = PolygonsGeodataframe.crs
print time.time()-start
merged=sjoin(PointsGeodataframe, PolygonsGeodataframe, how='left')
print time.time()-start
merged.to_csv("K:/01. Personal/04. Models/10. Location/output.csv",index=None)
print time.time()-start
python
spatial-join
geopandas
rtree
Alexis Eggermont
fuente
fuente
Respuestas:
Agregar el argumento op = 'inside' en la función sjoin acelera dramáticamente la operación de punto en el polígono.
El valor predeterminado es op = 'intersecta', lo que supongo que también conduciría a un resultado correcto, pero es de 100 a 1000 veces más lento.
fuente
within
es por lo general de alguna manera más rápida, la respuesta de nick_g Lea a continuación.La pregunta pregunta cómo aprovechar el r-tree en uniones espaciales geopandas, y otro respondedor señala correctamente que debe usar 'dentro' en lugar de 'intersecta'. Sin embargo, también puede aprovechar un índice espacial de r-tree en geopandas mientras usa
intersects
/intersection
, como se demuestra en este tutorial de geopandas r-tree :fuente
Lo que probablemente está sucediendo aquí es que solo el marco de datos de la derecha se alimenta al índice rtree: https://github.com/geopandas/geopandas/blob/master/geopandas/tools/sjoin.py#L48-L55 Que para un
op="intersects"
ejecutar significaría que el Polígono se introdujo en el índice, por lo que para cada punto, el polígono correspondiente se encuentra a través del índice rtree.Pero para
op="within"
, los geodataframes se voltean ya que la operación es en realidad la inversa decontains
: https://github.com/geopandas/geopandas/blob/master/geopandas/tools/sjoin.py#L41-L43Entonces, lo que sucedió cuando cambió
op
deop="intersects"
aop="within"
es que para cada polígono, los puntos correspondientes se encuentran a través del índice rtree, que en su caso aceleró la consulta.fuente