Samt to måter å opprette GeoDataFrames på.
Referanser som gir bakgunn for å forstå eksemplene nedenfor:
NTNU 01.03.2021 - Sverre Stikbakke NTNU 26.03.2022 - Oppdatert med Spatial Join og Overlay
import pandas as pd
import geopandas as gpd
import fiona as fi
from shapely.geometry import Polygon, Point
# Python dictionary (en innebygd datastruktur i Python)
data = {'smaragd': {
'localid': 446124344,
'objtype': 'Teig',
'SHAPE_Length': 306.207095792018,
'SHAPE_Area': 5747.21023925478,
'geometry': Polygon([
[591518.2, 6740464.0499],
[591442.74, 6740401.1999],
[591399.69, 6740452.8699],
[591460.55, 6740518.9299],
[591464.35, 6740525.3999],
[591471.27, 6740517.5099],
[591516.35, 6740466.1499],
[591518.2, 6740464.0499],
]),
}, 'beryll': {
'localid': 49174530,
'objtype': 'Teig',
'SHAPE_Length': 306.207095792018,
'SHAPE_Area': 5747.21023925478,
'geometry': Polygon([
[591535.31, 6740542.8499],
[591546.79, 6740525.9499],
[591565.3179, 6740498.2083],
[591527.4193, 6740467.2872],
[591516.35, 6740466.1499],
[591471.27, 6740517.5099],
[591464.35, 6740525.3999],
[591494.5, 6740576.6499],
[591514.4, 6740554.4999],
[591525.4, 6740550.7899],
[591535.31, 6740542.8499],
]),
}}
teiger = gpd.GeoDataFrame.from_dict(data, orient='index')
teiger.crs = 'EPSG:25832'
teiger.plot(figsize=(12,12))
# Hele geometri-kolonnen er en GeoSeries
print(teiger.loc[:, 'geometry'])
print(type(teiger.loc[:, 'geometry']))
# Ett element i en GeoSeries er en Shapely geometri-type
print(teiger.loc['smaragd', 'geometry'])
print(type(teiger.loc['smaragd', 'geometry']))
# Her henter vi ut geometriene hver for seg og tester relasjonen mellom dem
print('Smaragd-teigen berører Beryll-teigen? ', teiger.loc['smaragd', 'geometry'].touches(teiger.loc['beryll', 'geometry']))
print('Smaragd-teigen ligger inne i Beryll-teigen? ', teiger.loc['smaragd', 'geometry'].contains(teiger.loc['beryll', 'geometry']))
print('Smaragd-teigen krysser (intersects) Beryll-teigen? ', teiger.loc['smaragd', 'geometry'].intersects(teiger.loc['beryll', 'geometry']))
print('Smaragd-teigen overlapper Beryll-teigen? ', teiger.loc['smaragd', 'geometry'].overlaps(teiger.loc['beryll', 'geometry']))
teiger.contains(Point([591437,6740440]))
# fila som importeres her har Geopackage-format. Det er eksportert fra QGIS.
bygninger = gpd.read_file('bygninger_buffer.gpkg')
# Plotte-kommandoen kan også gjøres direkte på GeoDataFrame
bygninger.plot(figsize=(15,15))
Vi ønsker å finne bygningene som ligger inne i teig-polygonene for Smaragd og Beryll.
I dokumentasjonen for contains leser vi: This method works in a row-wise manner
Vi må derfor tvinge GeoPandas til å gjøre contains-testen på alle de andre radene også, som vist nedenfor.
# oppdaterer bygninger med en ny kolonne, Beryll_Smaragd, med True/False, som angir om bygningene ligger innenfor noen av teig-polygonene
bygninger['Beryll_Smaragd'] = bygninger.geometry.apply(lambda x: teiger.geometry.contains(x).any())
# betingelsen inne i parentesen angir hvilke rader som skal hentes ut.
bygninger_Beryll_Smaragd = bygninger[bygninger.Beryll_Smaragd == True]
bygninger_Beryll_Smaragd
bygninger_Beryll_Smaragd.plot(figsize=(6,10))
Egenhofer-relasjonene som er vist ovenfor tilhører GeoSeries-objektet og opererer radvis. Geopandas har også funksjoner som tilsvarer det vi finner i GIS-systemer som ArcGIS og QGIS og som automatisk krysstester alle geometrier.
Se spatial join og overlay. I dette tilfellet vil disse metoden gi samme resultat.
I dokumentasjonen for GeoPandas finner vi disse under API/Tools.
bygninger_Beryll_Smaragd_sjoin = gpd.sjoin(bygninger, teiger)
bygninger_Beryll_Smaragd_sjoin.plot(figsize=(6,10))
bygninger_Beryll_Smaragd_overlay = gpd.overlay(bygninger, teiger)
bygninger_Beryll_Smaragd_overlay.plot(figsize=(6,10))