Oppretting av GeoDataFrame med .from_dict -funksjon (fra dictionary)

In [1]:
import pandas as pd
import geopandas as gpd
import fiona as fi
from shapely.geometry import Polygon, Point
In [2]:
# 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],
        ]),
    }}
In [3]:
teiger = gpd.GeoDataFrame.from_dict(data, orient='index')
teiger.crs = 'EPSG:25832'
In [4]:
teiger.plot(figsize=(12,12))
Out[4]:
<AxesSubplot:>

Egenhofer-relasjoner testet på enkelt-geometrier

In [5]:
# Hele geometri-kolonnen er en GeoSeries
print(teiger.loc[:, 'geometry'])
print(type(teiger.loc[:, 'geometry']))
smaragd    POLYGON ((591518.200 6740464.050, 591442.740 6...
beryll     POLYGON ((591535.310 6740542.850, 591546.790 6...
Name: geometry, dtype: geometry
<class 'geopandas.geoseries.GeoSeries'>
In [6]:
# Ett element i en GeoSeries er en Shapely geometri-type
print(teiger.loc['smaragd', 'geometry'])
print(type(teiger.loc['smaragd', '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))
<class 'shapely.geometry.polygon.Polygon'>
In [7]:
# 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']))
Smaragd-teigen berører Beryll-teigen?  True
Smaragd-teigen ligger inne i Beryll-teigen?  False
Smaragd-teigen krysser (intersects) Beryll-teigen?  True
Smaragd-teigen overlapper Beryll-teigen?  False
In [8]:
teiger.contains(Point([591437,6740440]))
Out[8]:
smaragd     True
beryll     False
dtype: bool

Oppretting av GeoDataframe ved innlesing fra fil

In [9]:
# fila som importeres her har Geopackage-format. Det er eksportert fra QGIS.
bygninger = gpd.read_file('bygninger_buffer.gpkg')
In [10]:
# Plotte-kommandoen kan også gjøres direkte på GeoDataFrame 
bygninger.plot(figsize=(15,15))
Out[10]:
<AxesSubplot:>

Egenhofer-relasjoner krysstestet mellom alle geometrier i to GeoDataFrames

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

row-wise

Vi må derfor tvinge GeoPandas til å gjøre contains-testen på alle de andre radene også, som vist nedenfor.

  • apply-funksjonen kjører en funksjon pÃ¥ alle elementene i en GeoSeries eller GeoDataFrame, her: GeoSeries (bygninger.geometry)
  • lambda er et Python-nøkkelord for Ã¥ definere en anonym funksjon - det vil si en funksjon uten navn, definert her for Ã¥ brukes bare her
  • x representerer en enkelt-geometri, det vil si ett element fra geometry-kolonnen. Gjennom apply-funksjonaliteten vil x representere alle geometri-elementene, én etter én
  • .any()-funksjonen returnerer True hvis noen av testene er sanne, her: at ett av teig-polygonene inneholder den aktuelle x'en, dvs. et bygningspolygon
In [11]:
# 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())
In [12]:
# betingelsen inne i parentesen angir hvilke rader som skal hentes ut.
bygninger_Beryll_Smaragd = bygninger[bygninger.Beryll_Smaragd == True]
bygninger_Beryll_Smaragd
Out[12]:
OBJECTID objtype bygningsnummer datafangstdato lokalid navnerom versjonid produkt versjon undertype ... kopidato bygningstype bygningsstatus kommunenummer innmalingsstatus medium SHAPE_Length SHAPE_Area geometry Beryll_Smaragd
91 3140 AnnenBygning NaN None 569d3e31-732e-4573-989d-e8974d99aa3b http://data.geonorge.no/SFKB/FKB-Bygning/so 2019-12-17 10:52:45.063000 None None None ... 2020-10-26T08:02:49 NaN None None None None 12.423114 9.16520 MULTIPOLYGON Z (((591464.400 6740433.940 184.9... True
283 9906 Bygning 7482434.0 2007-04-30T00:00:00 a1d5cdb0-2cab-4630-90f8-db5360a4e6bf http://data.geonorge.no/SFKB/FKB-Bygning/so 2019-12-17 10:52:45.063000 None None None ... 2020-10-26T08:03:00 621.0 TB 3407 None None 147.531351 894.65440 MULTIPOLYGON Z (((591482.390 6740523.390 198.8... True
834 29039 Bygning 300671356.0 None a174bb93-fb90-4bd3-b4df-97f6528abe83 http://data.geonorge.no/SFKB/FKB-Bygning/so 2019-12-17 10:52:45.063000 None None None ... 2020-10-26T08:03:51 621.0 FA 3407 None None 163.858066 1581.58470 MULTIPOLYGON Z (((591457.090 6740476.920 191.2... True
1048 34964 Takoverbygg NaN None 229bad4a-ad07-4ec4-a139-d85aaab70abf http://data.geonorge.no/SFKB/FKB-Bygning/so 2019-12-17 10:52:45.063000 None None None ... 2020-10-26T08:08:36 NaN None None None None 19.758782 24.19165 MULTIPOLYGON Z (((591516.280 6740536.880 190.1... True

4 rows × 26 columns

In [13]:
bygninger_Beryll_Smaragd.plot(figsize=(6,10))
Out[13]:
<AxesSubplot:>

En enklere måte - bruk av Spatial Join- eller Overlay-funksjon

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.

In [14]:
bygninger_Beryll_Smaragd_sjoin = gpd.sjoin(bygninger, teiger)

bygninger_Beryll_Smaragd_sjoin.plot(figsize=(6,10))
Out[14]:
<AxesSubplot:>
In [15]:
bygninger_Beryll_Smaragd_overlay = gpd.overlay(bygninger, teiger)

bygninger_Beryll_Smaragd_overlay.plot(figsize=(6,10))
Out[15]:
<AxesSubplot:>