Mam 2 ramki geodata:
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'])
i chcę znaleźć nazwę najbliższego punktu w gpd2 dla każdego wiersza w 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
Próbowałem uruchomić to za pomocą funkcji lambda:
gpd1['Nearest'] = gpd1.apply(lambda row: min_dist(row.geometry,gpd2)['Place'] , axis=1)
z
def min_dist(point, gpd2):
geoseries = some_function()
return geoseries
Odpowiedzi:
Możesz bezpośrednio użyć funkcji Shapely Najbliższe punkty (geometrie GeoSeries są geometriami Shapely):
Rozwinięcie
źródło
sample_point = gpd2.geometry.unary_union[400] /
sample_point in gpd2.geometry
Zwraca wartość True.gpd2.geometry == sample_point
To wychodzi na wszystkie fałszywe.gpd2.geometry.geom_equals(sample_point)
działa.Jeśli masz duże ramki danych, zauważyłem, że metoda
scipy
indeksu przestrzennego cKDTree.query
zwraca bardzo szybkie wyniki wyszukiwania najbliższego sąsiada. Ponieważ wykorzystuje indeks przestrzenny, jego rzędy wielkości są szybsze niż zapętlanie przez ramkę danych, a następnie znajdowanie minimum wszystkich odległości. Jest także szybszy niż używanie foremnychnearest_points
z RTree (metoda indeksu przestrzennego dostępna za pośrednictwem geopandas), ponieważ cKDTree pozwala na wektoryzację wyszukiwania, podczas gdy druga metoda tego nie robi.Oto funkcja pomocnika, która zwróci odległość i „imię” najbliższego sąsiada
gpd2
z każdego punktu wgpd1
. Zakłada się, że oba pliki gdf majągeometry
kolumnę (punktów).A jeśli chcesz znaleźć najbliższy punkt LineString, oto pełny działający przykład:
źródło
Domyśliłam się:
Oczywiście krytyka jest mile widziana. Nie jestem fanem przeliczania gpd2 ['Dist'] dla każdego wiersza gpd1 ...
źródło
Odpowiedź Gene'a nie zadziałała dla mnie. W końcu odkryłem, że gpd2.geometry.unary_union zaowocowało geometrią, która zawierała tylko około 30 000 z moich ogółem około 150 000 punktów. Dla każdego, kto napotka ten sam problem, oto jak go rozwiązałem:
źródło
Dla każdego, kto ma błędy indeksowania z własnymi danymi podczas korzystania z doskonałej odpowiedzi z @ JHuw , moim problemem było to, że moje indeksy nie były wyrównane. Zresetowanie indeksu gdfA i gdfB rozwiązało moje problemy, być może może to również pomóc @ Shakedk .
źródło