Geopandas räumliche Verbindung extrem langsam


12

Ich verwende den folgenden Code, um ein Land (und manchmal einen Bundesstaat) für Millionen von GPS-Punkten zu finden. Der Code benötigt derzeit ungefähr eine Sekunde pro Punkt, was unglaublich langsam ist. Das Shapefile ist 6 MB groß.

Ich habe gelesen, dass Geopandas rtrees für räumliche Verknüpfungen verwenden, was sie unglaublich effizient macht, aber das scheint hier nicht zu funktionieren. Was mache ich falsch? Ich habe auf tausend Punkte pro Sekunde gehofft.

Das Shapefile und die CSV können hier heruntergeladen werden (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

Antworten:


16

Das Hinzufügen des Arguments op = 'within' in der sjoin-Funktion beschleunigt die Point-in-Polygon-Operation erheblich.

Der Standardwert ist op = 'intersects', was meines Erachtens ebenfalls zu einem korrekten Ergebnis führen würde, aber 100- bis 1000-mal langsamer ist.


Für jeden, der dies liest, bedeutet dies nicht, dass withines im Allgemeinen irgendwie schneller ist. Lesen Sie dazu die Antwort von nick_g weiter unten.
Inc42

7

In der Frage wird gefragt, wie Sie die Vorteile von R-Tree in räumlichen Geopanda-Joins nutzen können. Ein anderer Responder weist korrekt darauf hin, dass Sie 'inside' anstelle von 'intersects' verwenden sollten. Sie können jedoch auch einen räumlichen R-Tree-Index in Geopandas verwenden, während Sie intersects/ verwenden intersection. Dies wird in diesem R-Tree-Tutorial für Geopandas veranschaulicht :

spatial_index = gdf.sindex
possible_matches_index = list(spatial_index.intersection(polygon.bounds))
possible_matches = gdf.iloc[possible_matches_index]
precise_matches = possible_matches[possible_matches.intersects(polygon)]

5

Was hier wahrscheinlich vor sich geht, ist, dass nur der rechte Datenrahmen in den rtree-Index eingespeist wird: https://github.com/geopandas/geopandas/blob/master/geopandas/tools/sjoin.py#L48-L55 Which for an op="intersects"run würde bedeuten, dass das Polygon in den Index eingespeist wurde, sodass für jeden Punkt das entsprechende Polygon durch den rtree-Index gefunden wird.

Aber für op="within"die geodataframes da der Betrieb umgedreht werden , ist eigentlich das Gegenteil von contains: https://github.com/geopandas/geopandas/blob/master/geopandas/tools/sjoin.py#L41-L43

Also , was passiert , wenn Sie die geschaltete opvon op="intersects"zu op="within"ist , dass für jedes Polygon, werden die entsprechenden Punkte durch den RTREE Index gefunden, die in Ihrem Fall die Abfrage beschleunigt.


1
Sie haben nicht permanente URLs verwendet. Können Sie diese möglicherweise auf eine bestimmte Revision aktualisieren?
Inc42
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.