Interaktiva kartor#

I det tidigare exemplet ritade vi en karta, som snabbt gav en bra helhetsbild över världens utsläppsfördelning. På kartan var nationerna färgade, så att mörkare färg innebar större utsläpp. Hur gör vi om vi vill kunna använda kartan för att se utsläppen eller annan statistik mer exakt?

I den här övningen ska vi göra en karta i samma stil, men vi ska också lägga till interaktiva egenskaper. Vi gör en sådan karta, som visar information om området i en pop-up-ruta när vi för pekaren över dem. För omväxlingens skull ska vi använda andra exempeldata än förra gången. Vi undersöker denna gång Finlands kommuner och pensionärernas andel av befolkningen.

Finlands kommungränser kan laddas ned från Lantmäteriverkets databank. Kartfilen hittas med namnet ”SuomenKuntajako_2020_250k.mid”.

Pensionärernas andel av befolkningen är också öppna data, och finns tillgängligt på Statistikcentralens hemsida. Vi har sparat och förberett filen lite för att den ska passa detta exempel bättre. Den hittas i datamappen som hör till detta dokument, under namnet ”elakelaisten_osuus_2018_kuntajako_2020.csv”. Namnet antyder att statistiken är från 2018, men den återges enligt kommunindelningen från 2020.

Läsa in data#

Vi påbörjar övningen likadant som tidigare, genom att ladda in datafilerna och förena dem till ett dataset. Vi använder funktionspaketen pandas och geopandas för att göra detta.

import pandas as pd
import geopandas as gpd

# Vi läser in kommungränserna med geopandas' read_file()-funktion
# encoding='latin1' gör att åäö fungerar som de ska.
cities = gpd.read_file('../data/SuomenKuntajako_2020_250k.mid', encoding='latin1')

# Vi kontrollerar hur datan ser ut.
cities.head()
gml_id natcode namefin nameswe landarea freshwarea seawarea totalarea geometry
0 1601100430 691 Reisjärvi Reisjärvi 474.60 28.74 0.00 503.34 MULTIPOLYGON (((418701.443 7055306.898, 418485...
1 1601100624 853 Turku Åbo 245.66 3.47 57.22 306.35 POLYGON ((249073.975 6725828.546, 248775.530 6...
2 1601100110 318 Kökar Kökar 63.57 0.43 2101.02 2165.02 POLYGON ((172798.744 6674623.732, 173415.386 6...
3 1601100668 859 Tyrnävä Tyrnävä 491.82 3.04 0.00 494.86 POLYGON ((440372.786 7197460.702, 440107.431 7...
4 1601100521 747 Siikainen Siikainen 463.29 28.02 0.00 491.31 POLYGON ((236801.933 6882124.138, 236897.467 6...
# Vi läser in filen med information om pensionärsbefolkningen med pandas' read_csv-funktion.
pensioners = pd.read_csv('../data/elakelaisten_osuus_2018_kuntajako_2020.csv')

# Vi kontrollerar hur tabellen ser ut.
pensioners.head()
alue elakelaisten_osuus
0 Akaa 27.3
1 Alajärvi 33.0
2 Alavieska 28.7
3 Alavus 32.7
4 Asikkala 37.2
# Vi kombinerar tabellerna baserat på kolumnerna med kommunnamn.
data = cities.merge(pensioners, left_on='namefin', right_on='alue')

# Vi kontrollerar resultatet
data.head()
gml_id natcode namefin nameswe landarea freshwarea seawarea totalarea geometry alue elakelaisten_osuus
0 1601100430 691 Reisjärvi Reisjärvi 474.60 28.74 0.00 503.34 MULTIPOLYGON (((418701.443 7055306.898, 418485... Reisjärvi 32.0
1 1601100624 853 Turku Åbo 245.66 3.47 57.22 306.35 POLYGON ((249073.975 6725828.546, 248775.530 6... Turku 24.2
2 1601100110 318 Kökar Kökar 63.57 0.43 2101.02 2165.02 POLYGON ((172798.744 6674623.732, 173415.386 6... Kökar 36.4
3 1601100668 859 Tyrnävä Tyrnävä 491.82 3.04 0.00 494.86 POLYGON ((440372.786 7197460.702, 440107.431 7... Tyrnävä 16.2
4 1601100521 747 Siikainen Siikainen 463.29 28.02 0.00 491.31 POLYGON ((236801.933 6882124.138, 236897.467 6... Siikainen 41.9

Rita en karta med hjälp av Bokeh#

Vi lyckades läsa in informationen! Nu ska vi få informationen att synas med hjälp av Bokeh-paketet. För att få fram bilden behöver vi följande funktioner:

  • figure(): Grundar bilden. Här kan man lägga till en titel för kartan med title-parametern.

  • GeoJSONDataSource: Ändrar vår data till GeoJSONDataSource-format, så att den fungerar bättre med Bokeh.

  • LinearColorMapper: Lägger till färg på kartan.

  • Greens: Områdena markeras med toner av grönt.

  • output_notebook(): Med detta kommando syns kartan under kodcellen (förutsatt att vi också använder show-kommandot). Annars skulle kartan öppnas i en annan flik.

  • show(): Detta kommando gör att bilden visas.

# Vi läser in funktionerna som behövs från deras respetive funktionsbibliotek.
from bokeh.plotting import figure
from bokeh.models import GeoJSONDataSource, LinearColorMapper
from bokeh.palettes import Greens
from bokeh.io import output_notebook, show

# Vi grundar en ny bild och väljer en titel. Vi sparar bilden som variabeln "fig"
fig = figure(title="Pensionärernas andel av befolkningen 2018 (enligt 2020 kommungränser). ")

# Vi ändrar vår data till json-format (.to_json) och sedan till GeoJSONDataSource.
data_json = data.to_json()
geosource = GeoJSONDataSource(geojson = data_json)

# Vi väljer en grönskala med 6 olika toner.
# [::-1] på slutet inverterar skalan, så att högre värden motsvaras av mörkare toner.
palette = Greens[6][::-1]

# Vi ska definiera en skala, och väljer det lägsta värdet som nedre gräns och det högsta värdet som övre gräns.
color_mapper = LinearColorMapper(palette = palette,
                                 low = data['elakelaisten_osuus'].min(),
                                 high = data['elakelaisten_osuus'].max())

# Vi ritar in kommungränserna på kartan.
# I GeoJSONDataSource-formatet har geometry-kolumnen ändrat till kolumnerna 'xs' och 'ys'
# Vi ritar gränserna utgående från 'geosource'-variabeln som vi definierade tidigare.
# Vi färglägger alla områden med fill_color-kommandot. Då behöver vi ange kolumnens namn och färgskalan.
fig.patches('xs','ys',
            source = geosource,
            fill_color={'field':'elakelaisten_osuus','transform': color_mapper})

# Vi ser till att resultatet visas här i samma notebook
output_notebook()

# Visa kartan
show(fig)
Loading BokehJS ...

Sådär! Nu fick vi kartan att synas med hjälp av Bokeh. Vi märker att andelen pensionärer är betydligt större i Östra Finland jämfört med t.ex. Huvudstadsregionen. Kustkommunerna, och speciellt Åland, ser lite märkliga ut eftersom också havsområden är markerade.

Kartan har redan några praktiska verktyg som låter oss dra och zooma kartan, eller spara den. Den här kartan kan i någon mån anses vara interaktiv, men vi vill göra en karta där vi kan se information om områden när vi för pekaren över dem. Då behöver vi också verktyget HoverTool från Bokeh-biblioteket.

from bokeh.models import HoverTool

# Vi kapar en HoverTool och sparar den som variabeln "hover".
hover = HoverTool()

# Vi lägger till "tooltips"-information, som komer att synas när vi för pekaren över området.
# Efter @-tecknet skriver vi in vilken kolumn informationen ska tas ifrån.
hover.tooltips = [('Kommun', '@nameswe'),('Pensionärernas andel (%)','@elakelaisten_osuus')]

# Vi lägger till "hover" bland kartans verktyg
fig.add_tools(hover)

# Visa bilden
output_notebook()
show(fig)
Loading BokehJS ...

Lysande! Nu kan vi söka upp rätt kommun med pekaren och se pensionärernas andel av befolkningen direkt och exakt. Och det behövdes inte ens många rader kod.

Testa själv att hämta någon kommun- eller landsindelad data och rita in det på en interaktiv karta. Sök någon information som intresserar dig. Lycka till!