Kartdata

Det er tilrettelagt kartdata i Dapla til analyse, statistikkproduksjon og visualisering. Det er de samme dataene som er i GEODB i vanlig produksjonssone. Kartdataene er lagret på ssb-kart-data-delt-prod. De er lagret som parquetfiler i standardprojeksjonen vi bruker i SSB (UTM sone 33N) hvis ikke annet er angitt. Det er også SSBs standard-rutenett i ulike størrelser samt Eurostats rutenett over Norge.

I tillegg ligger det noe testdata i fellesbøtta her: ssb-prod-dapla-felles-data-delt/GIS/testdata

Python

GIS-pakker og lesing/skriving av geodata

Geopandas er et Python-bibliotek som integrerer Pandas med GIS-analysering og kartlegging. Geopandas er bygd opp rundt GeoDataFrames, som er en pandas DataFrame med geografisk informasjon. Disse kan lastes inn direkte hvis man har geografiske filer, eller man kan konvertere fra DataFrames med koordinat-kolonner (se eksempel under).

Geopandas kan blant annet brukes til å kartlegge dataene, beregne avstander og labe variabler for nærmiljø ved å koble datasett sammen basert på geografisk overlapp.

For lesing og skriving av geodata i Dapla, kan man bruke SSB-pakken sgis. Med denne kan man blant annet også beregne reisetider langs veg og lage publiseringsverdige kart.

Pakkene kan installeres i Dapla sånn her:

terminal
poetry add geopandas
poetry add ssb-sgis

Og så importeres det i Python på vanlig vis.

notebook
import geopandas as gpd
import sgis as sg

Eksempel på lesing/skriving av kartdata

Man kan lese/skrive geodata i Dapla med sgis-funksjonene read_geopandas og write_geopandas. Støttede formater er blant annet (geo)parquet, geojson og gml. En rekke kartdata for hele landet til analyse- og visualiseringsformål ligger i bøtta “kart”. For eksempel kommuneflater til analyse eller statistikk:

notebook
filsti = "ssb-kart-data-delt-prod/analyse_data/klargjorte-data/2024/ABAS_kommune_flate_p2024_v1.parquet"
kommuner = sg.read_geopandas(filsti)

Eksempel på lesing av kommuneflater for visualisering. Disse dataene er generalisert slik at de egner seg for å lage kart, men blir unøyaktige til statistikk:

notebook
filsti = "ssb-kart-data-delt-prod/visualisering_data/klargjorte-data/2024/parquet/N5000_kommune_flate_p2024_v1.parquet"
kommuner = sg.read_geopandas(filsti)

Tilsvarende for skriving til parquet eller annet geodataformat:

notebook
sg.write_geopandas(kommuner, filsti_ny) 

Man kan også gjøre vanlige tabell-filer geografiske hvis man har koordinat-kolonner. For eksempel situasjonsuttak fra Virksomhets- og foretaksregisteret (VoF):

notebook
import dapla as dp

VOFSTI = "ssb-vof-data-delt-stedfesting-prod/klargjorte-data/parquet"
vof_df = dp.read_pandas(
    f"{VOFSTI}/stedfesting-situasjonsuttak_p2023-01_v1.parquet"
)
vof_gdf = gpd.GeoDataFrame(
    vof_df, 
    geometry=gpd.points_from_xy(
        vof_df["y_koordinat"],
        vof_df["x_koordinat"],
    ),
    crs=25833,
)
vof_gdf

geopandas-eksempler i Dapla

I tillegg til kartdataene, ligger det testdata i fellesbøtta som man kan leke seg med. Testdataene finnes for Oslo og Kongsvinger, og kan leses sånn her:

notebook
testdatasti = "ssb-prod-dapla-felles-data-delt/GIS/testdata"
veger = sg.read_geopandas(f"{testdatasti}/veger_oslo.parquet")

Under følger noen eksempler på GIS-prosessering med testdataene.

Eksempel på avstandsberegning

Avstand i luftlinje finner man enkelt med sjoin_nearest. Sånn her finner man avstand fra boligbygg (1000 tilfeldige) i Oslo til nærmeste butikkbygg.

notebook
boligbygg = sg.read_geopandas(f"{testdatasti}/noen_boligbygg_oslo.parquet")
butikkbygg = sg.read_geopandas(f"{testdatasti}/butikkbygg_oslo.parquet")

boligbygg_med_butikkavstand = boligbygg.sjoin_nearest(butikkbygg, distance_col="meter_til_butikk")

For å finne avstand eller reisetid langs veier, kan man gjøre nettverksanalyse med sgis. Man må først klargjøre vegnettet og bestemme regler for beregningen(e):

notebook
veger_klargjort = (
    sg.get_connected_components(veger)
    .loc[lambda x: x["connected"] == 1]
    .pipe(sg.make_directed_network_norway, dropnegative=True)
)

regler = sg.NetworkAnalysisRules(directed=True, weight="minutes")

nwa = sg.NetworkAnalysis(network=veger_klargjort, rules=regler)

Så kan man beregne reisetider fra boligbygg til butikkbygg:

notebook
avstander = nwa.od_cost_matrix(boligbygg, butikkbygg)

Korteste reisetid per bolig kan kobles på som kolonne i boligdataene sånn her:

notebook
boligbygg["minutter_til_butikk"] = avstander.groupby("origin")["minutes"].min()

Undersøk resultatene i interaktivt kart:

notebook
sg.explore(boligbygg, butikkbygg, "minutter_til_butikk")

Se mer informasjon og eksempler i dokumentasjonen.

Og flere nettverksanalyse-eksempler her.

Eksempel på geografisk kobling

Datasett kan kobles basert på geografisk overlapp med geopandas.sjoin. Denne fungerer akkurat som pandas.merge, bare at det kobles basert på geometrien.

Kodesnutten under returnerer én kommuneflate for hvert bygg som overlapper, med kolonner fra begge datasettene. Inner-join er default, men med left-join beholder man også geometriene som ikke overlapper.

notebook
kommuner = sg.read_geopandas(f"{testdatasti}/enkle_kommuner.parquet")
kommuner_med_boliginfo = kommuner.sjoin(boligbygg, how="left")

Med motsatt rekkefølge, får man ett boligbygg per kommune den overlapper med. Siden byggene er punkter, vil hvert bygg havne i maksimalt én kommune.

notebook
boligbygg_med_kommuneinfo = boligbygg.sjoin(kommuner, how="left")

Eksempel på å lage kart

Man kan lage tematiske kart med sgis-klassen ThematicMap. Her er et enkelt eksempel på et kart over arealet i kommuner.

notebook
kommuner["Kvadratmeter"] = kommuner.area

m = sg.ThematicMap(kommuner, column="Kvadratmeter", size=15)
m.title = "Areal i kommunene"
m.plot()

Se flere kart-eksempler her.

Konvertere DataFrame til GeoDataFrame

En pandas.DataFrame med koordinat-kolonner, kan konverteres til GeoDataFrame sånn her:

notebook
import pandas as pd
df = pd.DataFrame({"x": [10.8, 10.7, 10.9], "y": [59.9, 60, 59.85]})

gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.x, df.y), crs=4326)

For å beregne avtand i meter og kunne koble med annen geodata i Dapla, må man ha UTM-koordinater (hvis man ikke hadde det fra før):

notebook
gdf = gdf.to_crs(25833)

Se også geopandas’ dokumentasjon for mer utfyllende informasjon.

R

Den viktigste GIS-pakken i R er sf. Pakken er bygd opp rundt sf-objekter, som er data.frames med geografisk informasjon. Man kan gjøre standard tidyverse-opersjoner på sf-objektene, pluss GIS-operasjoner.

Sindre Mikael Haugen har lagd funksjoner for å lese og skrive blant annet geodata i Dapla. For å få geodata, setter man parametret ‘sf’ til TRUE:

notebook
library(fellesr)

veger = read_SSB("ssb-prod-dapla-felles-data-delt/GIS/testdata/veger_oslo.parquet", sf = TRUE)

Haugen har også lagd en pakke for å gjøre nettverksanalyse, som også lar deg geokode adresser, altså å finne adressenes koordinater.

notebook
library(GISSB)

Lite eksempel på kobling basert geografisk sammenfall (enkle kommuner er egentlig til visualisering). Her får man ett bygg per kommune som overlapper (som maksimalt er én kommune siden dette er bygningspunkter):

notebook
library(sf)

boligbygg = read_SSB("ssb-prod-dapla-felles-data-delt/GIS/testdata/noen_boligbygg_oslo.parquet", sf = TRUE)
enkle_kommuner = read_SSB("ssb-prod-dapla-felles-data-delt/GIS/testdata/enkle_kommuner.parquet", sf = TRUE)

boligbygg_med_kommuneinfo = st_join(boligbygg, enkle_kommuner)

Med motsatt rekkefølge, får man én kommuneflate per bolig som overlapper:

notebook
kommuner_med_boliginfo = st_join(enkle_kommuner, boligbygg)