geopandy łączą się przestrzennie bardzo wolno

14

Korzystam z poniższego kodu, aby znaleźć kraj (a czasem stan) dla milionów punktów GPS. Kod zajmuje obecnie około jednej sekundy na punkt, co jest niezwykle powolne. Plik shapefile ma 6 MB.

Czytałem, że geopandy wykorzystują rtree do połączeń przestrzennych, co czyni je niesamowicie wydajnymi, ale wydaje się, że to tutaj nie działa. Co ja robię źle? Miałem nadzieję na tysiąc punktów na sekundę.

Plik shapefile i csv można pobrać tutaj (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
Alexis Eggermont
źródło
Twój link do danych to 404
Aaron

Odpowiedzi:

17

dodanie argumentu op = 'Within' w funkcji sjoin znacznie przyspiesza operację punkt-w-wielokącie.

Wartość domyślna to op = „przecina się”, co, jak sądzę, również doprowadziłoby do poprawnego wyniku, ale jest 100 do 1000 razy wolniejsze.

Alexis Eggermont
źródło
Aby ktoś czyta to, to nie znaczy, że withinjest generalnie jakoś szybciej czytać nick_g za odpowiedź poniżej.
inc42
7

Pytanie dotyczy sposobu wykorzystania r-drzewa w połączeniach przestrzennych geopandas, a inny respondent prawidłowo wskazuje, że należy używać „wewnątrz” zamiast „przecina się”. Jednak możesz również skorzystać z indeksu przestrzennego r-drzewa w geopandach podczas używania intersects/ intersection, jak pokazano w tym samouczku r-drzewa geopandas :

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)]
eos
źródło
6

Prawdopodobnie dzieje się tutaj to, że tylko ramka danych po prawej stronie jest wprowadzana do indeksu rtree: https://github.com/geopandas/geopandas/blob/master/geopandas/tools/sjoin.py#L48-L55 Co za op="intersects"Uruchomienie oznaczałoby, że wielokąt został wprowadzony do indeksu, więc dla każdego punktu odpowiadający mu wielokąt znajduje się na podstawie indeksu rtree.

Ale dla op="within", geodataframes są odwrócone, ponieważ operacja jest odwrotnością contains: https://github.com/geopandas/geopandas/blob/master/geopandas/tools/sjoin.py#L41-L43

Więc po zmianie opz op="intersects"na op="within"to, co się wydarzyło , dla każdego wielokąta odpowiednie punkty znajdują się w indeksie rtree, co w twoim przypadku przyspieszyło zapytanie.

nick_g
źródło
1
Użyłeś niestałych adresów URL, czy mógłbyś je zaktualizować do konkretnej wersji?
inc42