Przecięcie wielokąta linii Geopandy

11

Próbuję znaleźć miejsce, w którym wiele linii przecina wielokąt dla dwóch różnych ramek geodanych:

from shapely.geometry import Polygon, LineString
import geopandas as gpd

polygon = Polygon([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)])
line1 = LineString([(0.5, 0.5), (0.7, 0.7)])
line2 = LineString([(0.9, 0.9), (0.2, 0.6)])


poly_gdf = gpd.GeoDataFrame(geometry=[polygon])
line_gdf = gpd.GeoDataFrame(geometry=[line1, line2])

Tak wyglądają powyższe ramki danych (jedna ma wielokąt, a druga dwie linie). Wydaje mi się, że obie linie przecinają wielokąt:

Wielokąt i linie

Jednak wynik przecięcia jest bardzo mylący:

print(line_gdf.intersects(poly_gdf))

0 Prawda

1 False

print(line1.intersects(polygon))
print(line2.intersects(polygon))

Prawdziwe

Prawdziwe

Dlaczego geopandas intersectmetoda daje inny wynik niż standardowy shapely?

Używam Python 3.5.3 i Geopandas 0.2.1 wszystkie na Anaconda.

bgordon
źródło
Kiedy mówisz, print(line.intersects(polygon))że masz dostęp do zmiennej, która nie jest zdefiniowana tak daleko, jak widzę. Zdefiniowałeś line1i line2wcześniej w kodzie. Nie wiem, dlaczego to zwróci Prawdę.
Paul
2
Chciałbym również znać odpowiedź na to pytanie. Wygląda na to, że do geodataframe można przypisać tylko jedną kolumnę geometrii. Myślę, że twoja ramka danych line_gdf próbuje dodać dwie kolumny geometrii. Sprawdź geopandas.org/data_structures.html#geodataframe
Paul
@Paul przeprosiny, print(line.intersects(polygon))był literówką. Zaktualizowałem pytanie, aby odnieść się do line1tego, co pierwotnie miałem na myśli.
bgordon,
@Paul Widzę z dokumentacji, jak posiadanie dwóch kolumn geometrii spowodowałoby problem, ale nie jestem pewien, dlaczego dwie kolumny geometrii zostałyby dodane w pierwszej kolejności.
bgordon,
line_gdf.infopotwierdza, że ​​masz tylko jedną kolumnę geometrii. Jestem zakłopotany. Sprawdzę, jeśli coś znajdę.
Paul,

Odpowiedzi:

7

Podczas porównywania ramek geodezyjnych z operacjami geometrii w Geopandzie, geometrie są najpierw dopasowywane przez indeks. W przypadku, gdy nie ma pasującego indeksu (ponieważ na przykład masz tylko jeden wielokąt), wynikiem będzie False.

Jeśli GeoSeriesmiałoby to porównać każdy obiekt w środku, musiałbyś odzyskać pełną prostokątną ramkę danych wartości boolowskich, a to prawdopodobnie byłoby bardzo nieefektywne.

Jeśli chcesz porównać wszystkie geometrie, masz dwie opcje. Pierwszym (i prawdopodobnie najłatwiejszym) jest użycie sjoinmetody geopandas :

gpd.sjoin(line_gdf, poly_gdf, op='intersects')

Zwraca to nową GeoDataFramegeometrię dla każdego obiektu w lewej ramce danych, powtarzaną dla każdej geometrii, którą przecinają po prawej stronie, z indeksem obiektu po prawej stronie, tj .:

                        geometry  index_right
0  LINESTRING (0.5 0.5, 0.7 0.7)            0
1  LINESTRING (0.9 0.9, 0.2 0.6)            0

Druga metoda to dla nas applymetoda pandy w GeoSeriescelu zwrócenia prostokątnej ramki danych:

line_gdf.geometry.apply(lambda g: poly_gdf.intersects(g))

Co z kolei zwraca (wraz ze wzrostem nieefektywności wraz ze wzrostem ramek danych):

index_right     0
index_left
0            True
1            True

Ogólnie rzecz biorąc, chyba że potrzebujesz matrycy kwadratowej, radzę trzymać się tej sjoinmetody.

om_henners
źródło