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-prod-kart-data-delt. 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.

Man søker om tilgang til dataene til kundeservice (tilgangsrollen kart-consumers), men bruk gjerne standard LDA-prosedyre som for øvrige data.

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:

poetry add geopandas
poetry add ssb-sgis

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

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:

filsti = "ssb-prod-kart-data-delt/kartdata_analyse/klargjorte-data/2023/ABAS_kommune_flate_p2023.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:

filsti = "ssb-prod-kart-data-delt/kartdata_visualisering/klargjorte-data/2023/parquet/N5000_kommune_flate_p2023.parquet"
kommuner = sg.read_geopandas(filsti)

Tilsvarende for skriving til parquet eller annet geodataformat:

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):

import dapla as dp

VOFSTI = "ssb-prod-vof-data-delt/stedfesting-situasjonsuttak_data/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:

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.

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):

veger_klargjort = (
    sg.get_connected_components(veger)
    .query("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:

avstander = nwa.od_cost_matrix(boligbygg, butikkbygg)

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

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

Undersøk resultatene i interaktivt kart:

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.

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.

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.

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:

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):

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:

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.

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):

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:

kommuner_med_boliginfo = st_join(enkle_kommuner, boligbygg)