💻 Interaktive kart#
Online kart har vært interaktive i lang tid: nesten alle online kart tillater å zoome inn og ut, å panorere i kartet, og å velge kartfunksjoner, eller ellers forespørre informasjon om dem.
Interaktivt innhold i nettsider, som online kart, er typisk implementert ved hjelp av JavaScript/ECMAScript, et skriptspråk opprinnelig rettet mot nettsider, primært, men brukt for mange andre applikasjoner.
I det åpne kildekoderiket finnes det en rekke forskjellige JavaScript biblioteker for interaktiv webkartografi, inkludert Leaflet, som vi vil bruke i denne leksjonen, og OpenLayers.
Ta det rolig, vi vil ikke måtte skrive en eneste linje med JavaScript; dette er et
Python kurs, tross alt. Heller, vi vil dra nytte av
Folium Python-pakken: den
hjelper med å lage interaktive Leaflet-kart fra data lagret i
geopandas.GeoDataFrame
s.
Folium ressurser
Finn mer informasjon om mulighetene til Folium-pakken på dens offisielle nettsider:
Opprette et enkelt interaktivt webkart#
Vi vil starte med å lage et enkelt interaktivt webkart som ikke inneholder noe annet enn et bakgrunnskart. Dette er for at vi skal bli vant til hvordan Folium’s syntaks fungerer, og hvilke trinn vi må ta.
Vi lager et folium.Map
-objekt, og spesifiserer rundt hvilken location
det skal sentreres
og på hvilket utgangs-zoomnivå (~0-20) kartet skal vises. Ved å sette
control_scale
til True
, får vi Folium til å vise en skala også.
import pathlib
NOTEBOOK_PATH = pathlib.Path().resolve()
DATA_MAPPE = NOTEBOOK_PATH / "data"
# Vi vil eksportere HTML-sider i løpet av denne leksjonen,
# la oss også forberede en utdatamappe for dem:
HTML_MAPPE = NOTEBOOK_PATH / "html"
HTML_MAPPE.mkdir(exist_ok=True)
import folium
interactive_map = folium.Map(
location=(59.665, 10.776),
zoom_start=10,
control_scale=True
)
interactive_map
Lagre det resulterende kartet#
For å lagre dette kartet til en HTML-fil som kan åpnes i en hvilken som helst nettleser,
bruk folium.Map.save()
:
interactive_map.save(HTML_MAPPE / "base-map.html")
Endre bakgrunnskartet#
Hvis du vil bruke et annet bakgrunnslag enn standard OpenStreetMap,
aksepterer folium.Map
parameteret tiles
, som kan referere til en av de
innebygde kartleverandørene.
Mens vi er i gang, la oss også variere senterlokasjonen og zoomnivået på kartet:
interactive_map = folium.Map(
location=(59.668, 10.763),
zoom_start=15,
tiles="cartodbpositron"
)
interactive_map
Eller vi kan peke på en egendefinert tiles URL:
interactive_map = folium.Map(
location=(59.668, 10.763),
zoom_start=15,
tiles="https://mt1.google.com/vt/lyrs=r&x={x}&y={y}&z={z}",
attr="Google maps",
)
interactive_map
Legg til en punktmarkør#
For å legge til en enkelt markør til et Folium kart, opprett en
folium.Marker
.
Gi en
folium.Icon
som parameter icon
for å påvirke hvordan markøren er stylet, og sett tooltip
for å vise en tekst når musepekeren beveger seg over den.
interactive_map = folium.Map(
location=(59.668, 10.763),
zoom_start=15
)
hippocampus = folium.Marker(
location=(59.668, 10.763),
tooltip="Hippocampus",
icon=folium.Icon(color="green", icon="ok-sign")
)
hippocampus.add_to(interactive_map)
interactive_map
Legg til et lag med punkter#
Folium støtter også å legge til hele lag, for eksempel, som
geopandas.GeoDataFrames
. Folium implementerer Leaflet’s geoJSON
lag i sin
folium.features.GeoJson
klasse. Vi kan initialisere en slik klasse (og lag)
med en geodataframe, og legge den til et kart. I eksempelet nedenfor bruker vi
adresser.gpkg
datasettet vi laget tidligere.
import geopandas
adresser = geopandas.read_file(DATA_MAPPE / "oslo_adresser" / "adresser.geojson")
adresser.head()
fid | address | id | adr | geometry | |
---|---|---|---|---|---|
0 | 1 | 25, Statsråd Mathiesens vei, Linderud, Bjerke,... | 100 | Statsråd Mathiesens vei 25, 0594 OSLO | POINT (10.83648 59.94104) |
1 | 2 | 15, Slimeveien, Bjørnholt, Søndre Nordstrand, ... | 101 | Slimeveien 15, 1275 OSLO | POINT (10.83432 59.83557) |
2 | 3 | Sognsveien 80, Konvallveien, Sogn, Nordre Aker... | 102 | Sognsveien 80, 0855 OSLO | POINT (10.72956 59.95011) |
3 | 4 | 5, Ullevålsveien, Hammersborg, St. Hanshaugen,... | 103 | Ullevålsveien 5, 0165 OSLO | POINT (10.74356 59.91863) |
4 | 5 | 30B, Nydalsveien, Nydalen, Nordre Aker, Oslo, ... | 104 | Nydalsveien 30b, 0484 OSLO | POINT (10.76402 59.9503) |
interactive_map = folium.Map(
location=(59.914, 10.744),
zoom_start=11
)
adresser_lag = folium.features.GeoJson(
adresser
)
adresser_lag.add_to(interactive_map)
interactive_map
Vi kan også legge til et popup-vindu på kartet vårt som viser adressene på interessepunktet ved å klikke:
interactive_map = folium.Map(
location=(59.914, 10.744),
zoom_start=11
)
popup = folium.GeoJsonPopup(
fields=["adr"],
aliases=["Adresse"],
localize=True,
labels=True,
style="background-color: yellow;",
)
adresser_lag = folium.features.GeoJson(
adresser,
popup=popup
)
adresser_lag.add_to(interactive_map)
interactive_map
Legg til et polygonlag#
I den følgende delen skal vi gjenbesøke et annet datasett som vi har jobbet med før: Befolkningsrutenettet for Oslo fra SSB.
rutenett = geopandas.read_file(
DATA_MAPPE
/ "ssb_rutenett"
/ "befolkning_250m_2023_oslo.shp"
)
rutenett.head()
fid | ru250m | pop_tot | geometry | |
---|---|---|---|---|
0 | 1.0 | 2.263751e+13 | 14 | POLYGON ((264000 6643000, 263750 6643000, 2637... |
1 | 2.0 | 2.264001e+13 | 177 | POLYGON ((264250 6643000, 264000 6643000, 2640... |
2 | 3.0 | 2.264251e+13 | 169 | POLYGON ((264500 6643000, 264250 6643000, 2642... |
3 | 4.0 | 2.264501e+13 | 261 | POLYGON ((264750 6643000, 264500 6643000, 2645... |
4 | 5.0 | 2.264751e+13 | 106 | POLYGON ((265000 6643000, 264750 6643000, 2647... |
Indekskolonne for koroplettkart
Vi vil bruke folium.Choropleth
for å vise befolkningsrutenettet. Koroplettkart
er mer enn bare polygon-geometrier, som kan vises som et
folium.features.GeoJson
-lag, akkurat som vi brukte for adressene, ovenfor. Snarere tar klassen seg av kategorisering av data, legger til en legende, og
noen flere små oppgaver for å raskt lage temakart.
Klassen forventer et inputdatasett som har en eksplisitt, str
-type, indeks
kolonne, da den behandler den geografiske inputen og den tematiske inputen som separate
datasett som må samles (se også, nedenfor, hvordan vi spesifiserer både
geo_data
og data
).
En god tilnærming for å lage en slik kolonne er å kopiere dataframens indeks
til en ny kolonne, for eksempel id
.
rutenett["id"] = rutenett.index.astype(str)
Nå kan vi lage koroplettlaget for polygoner, og legge det til et kartobjekt. På grunn av den litt komplekse arkitekturen til Folium, må vi gi en rekke parametere:
geo_data
ogdata
, geografiske og tematiske inputdatasett, henholdsvis. Kan være den sammegeopandas.GeoDataFrame
en.columns
: en tuple av navnene på relevante kolonner idata
: en unik indekskolonne, og kolonnen som inneholder tematiske datakey_on
: hvilken kolonne igeo_data
som skal brukes for å kobledata
(dette er i utgangspunktet identisk medcolumns
, bortsett fra at det bare er den første verdien)
interactive_map = folium.Map(
location=(59.914, 10.744),
zoom_start=11
)
rutenett1 = folium.Choropleth(
geo_data=rutenett,
data=rutenett,
columns=("id", "pop_tot"),
key_on="feature.id"
)
rutenett1.add_to(interactive_map)
interactive_map
For å gjøre kartet litt finere, la oss fortsatt be om flere kategorier (bins
),
endre fargeområdet (ved hjelp av fill_color
), sett linjetykkelsen til null,
og legge til en tittel til legenden:
interactive_map = folium.Map(
location=(59.914, 10.744),
zoom_start=11
)
rutenett1 = folium.Choropleth(
geo_data=rutenett,
data=rutenett,
columns=("id", "pop_tot"),
key_on="feature.id",
bins=9,
fill_color="YlOrRd",
line_weight=0,
legend_name="Befolkning, 2023",
highlight=True
)
rutenett1.add_to(interactive_map)
interactive_map
Legg til en tooltip til et koroplettkart#
I et slikt interaktivt kart, ville det være fint å vise verdien av hvert
rutenett-polygon når du holder musepekeren over det. Folium støtter ikke
dette out-of-the-box, men med et enkel triks kan vi utvide funksjonaliteten:
Vi legger til et gjennomsiktig polygonlag ved hjelp av en ‘grunnleggende’ folium.features.GeoJson
,
og konfigurerer den til å vise tooltips.
Vi kan beholde map
som vi laget ovenfor, og bare legge til et annet lag på det..
# folium GeoJson lag forventer en stylingfunksjon,
# som mottar hver av kartets funksjon og returnerer
# en individuell stil. Den kan imidlertid også returnere en
# statisk stil:
def style_function(feature):
return {
"color": "transparent",
"fillColor": "transparent"
}
# Mer komplekse tooltips kan lages ved hjelp av
# `folium.features.GeoJsonTooltip` klassen. Nedenfor bruker vi
# dens mest grunnleggende funksjoner: `fields` spesifiserer hvilke kolonner
# som skal vises, `aliases` hvordan de skal være merket.
tooltip = folium.features.GeoJsonTooltip(
fields=("pop_tot",),
aliases=("Befolkning:",)
)
tooltip_layer = folium.features.GeoJson(
rutenett,
style_function=style_function,
tooltip=tooltip
)
tooltip_layer.add_to(interactive_map)
interactive_map
Python-pakker for interaktive (web) kart
Folium er bare en av mange pakker som gir en enkel måte å lage interaktive kart ved hjelp av data lagret i (geo-)pandas dataframer. Andre interessante biblioteker inkluderer:
Plotly Express, og mange flere.