Mikä latausasema kannattaisi pitää pystyssä hinnalla millä hyvänsä?

Latausverkko jakaumana, osa 7: kestävyys, riskikartta ja Lapin eristäminen

Latausverkon toimivuus näkyy vasta kun jotain hajoaa. Poistamme asemia yksi kerrallaan ja mittaamme, kuinka paljon koko maan saavutettavuus heikkenee. Tuloksena on kartta, joka kertoo mitkä asemat pitävät verkkoa kasassa.

avoin data
verkostoanalyysi
latausverkko
riskianalyysi
kestävyys
Author

Kristian Vepsäläinen

Published

13.10.2026

Verkko näyttää hyvältä siihen asti kun se ei näytä

Latausverkon tilaa arvioidaan sen mukaan, miten se toimii normaalisti. Kuinka monta asemaa on, kuinka kaukana ne ovat, kuinka moni käyttää niitä.

Nämä mittarit kuvaavat verkkoa hyvässä säässä. Infrastruktuurin arvo mitataan kuitenkin siinä, mitä tapahtuu kun jokin pettää — ja se ei näy normaalitilan mittareista lainkaan.

Asema voi olla epäkunnossa, sähköt voivat olla poikki, maksujärjestelmä voi kaatua, tai kaikki latauspaikat voivat olla varattuja juhannusaattona. Autoilijalle nämä tarkoittavat samaa asiaa: asema on siinä mutta sitä ei voi käyttää.

Tässä osassa poistan asemia yksi kerrallaan ja mittaan, kuinka paljon koko maan saavutettavuus heikkenee. Lopputulos on kartta, jossa jokainen asema on väritetty sen mukaan, kuinka paljon sen katoaminen haittaisi.

Se on eri kartta kuin lista suurimmista tai vilkkaimmista asemista.

Menetelmä: poista yksi, mittaa kaikki

Idea on yksinkertainen. Lasketaan ensin, kuinka kaukana lähin suurtehulaturi on jokaisesta postinumeroalueesta. Sitten poistetaan yksi asema ja lasketaan sama uudelleen. Erotus kertoo, kuinka paljon tuo asema oli tuomassa saavutettavuutta.

Kun tämä toistetaan jokaiselle asemalle, saadaan jokaiselle asemalle luku: paljonko koko maan saavutettavuus heikkenisi, jos tämä asema katoaisi huomenna.

Laskenta on kevyempi kuin miltä kuulostaa. Kun etäisyydet jokaisesta alueesta jokaiseen asemaan on kerran laskettu, aseman poistaminen tarkoittaa vain yhden sarakkeen pudottamista taulukosta ja rivikohtaisen pienimmän arvon etsimistä uudelleen. Reititystä ei tarvitse tehdä uudelleen.

Code
hpc <- liitokset |>
  filter(teho_kw >= 150) |>
  group_by(avain) |>
  summarise(max_kw = max(teho_kw, na.rm = TRUE), pistokkeita = n(),
            .groups = "drop") |>
  left_join(asemat, by = "avain") |>
  filter(!is.na(lat), !is.na(lon))

stopifnot(
  "Suurtehulatureita ei löytynyt" = nrow(hpc) > 50,
  "Koordinaatit Suomen ulkopuolella" =
    all(between(hpc$lat, 59.4, 70.2) & between(hpc$lon, 18.9, 31.7))
)

matriisi_path <- file.path(data_dir, "saavutettavuusmatriisi.qs")

if (!file.exists(matriisi_path)) {
  from <- pno |>
    st_transform(4326) |> st_coordinates() |>
    as_tibble() |> setNames(c("x", "y")) |> as.matrix()

  ajat <- dodgr_times(
    graph = tieverkko, from = from,
    to = as.matrix(select(hpc, x = lon, y = lat))
  ) / 60

  dimnames(ajat) <- list(pno$pno, hpc$avain)
  qs2::qs_save(ajat, matriisi_path)
} else {
  ajat <- qs2::qs_read(matriisi_path)
}

stopifnot(
  "Matriisin koko ei täsmää" =
    nrow(ajat) == nrow(pno) && ncol(ajat) == nrow(hpc),
  "Matriisissa on negatiivisia aikoja" = all(ajat >= 0, na.rm = TRUE)
)

# Alueet, joista ei pääse yhdellekään asemalle, jätetään pois: ne eivät
# reagoi minkään aseman poistamiseen eivätkä siis kerro kriittisyydestä.
nyky_min <- apply(ajat, 1, \(r) min(r, na.rm = TRUE))
kelpo <- is.finite(nyky_min) & pno$asukkaat > 0

ajat_k <- ajat[kelpo, , drop = FALSE]
vakiluku <- pno$asukkaat[kelpo]
arkiriippuvaiset <- pno$arkiriippuvaiset[kelpo]
nyky <- nyky_min[kelpo]

stopifnot(
  "Yli 10 % alueista jäi ulkopuolelle" = mean(kelpo) > 0.90,
  "Väkilukuja puuttuu" = all(!is.na(vakiluku)),
  "Arkiriippuvaisten painoja puuttuu" = all(!is.na(arkiriippuvaiset))
)

nyky_keskiaika <- weighted.mean(nyky, vakiluku)
arkiriippuvaisia_yht <- sum(arkiriippuvaiset)
arkiosuus <- arkiriippuvaisia_yht / sum(vakiluku)
Code
# Jokaisen aseman poisto vuorollaan. Poisto = sarakkeen pudotus ja
# rivikohtaisen minimin laskenta uudelleen.
#
# Vaikutusta EI mitata koko maan keskiarvona. Kriittisinkin asema koskettaa
# vain murto-osaa väestöstä, joten koko maan yli jaettuna sen katoaminen
# näyttää muutaman sekunnin asialta. Kolme lukua kertoo sen, minkä yksi
# keskiarvo peittää: keitä koskee, kuinka paljon heitä koskee, ja kuinka
# moni ylittää kipurajan.
kipuraja_min <- 30

poistovaikutus <- map_dfr(seq_len(ncol(ajat_k)), function(j) {
  uusi_min <- apply(ajat_k[, -j, drop = FALSE], 1, \(r) min(r, na.rm = TRUE))

  # Osa alueista voi menettää yhteyden kokonaan
  katkeaa <- !is.finite(uusi_min) & is.finite(nyky)
  muutos <- ifelse(katkeaa, NA_real_, uusi_min - nyky)

  koskee <- !is.na(muutos) & muutos > 0.5

  tibble(
    avain = colnames(ajat_k)[j],
    # Keitä koskee
    asukkaita_koskee = sum(vakiluku[koskee]),
    # Keitä koskee arjessa: vain ne, joilla ei ole kotilatausta
    arkiriippuvaisia_koskee = sum(arkiriippuvaiset[koskee]),
    # Kuinka paljon koskee niitä, joita se koskee
    kasvu_koskeville = if (any(koskee))
      weighted.mean(muutos[koskee], vakiluku[koskee]) else 0,
    # Kokonaisvaikutus: menetettyjä henkilöminuutteja latauskertaa kohti
    henkilominuutteja = sum(muutos[koskee] * vakiluku[koskee]),
    # Sama arkikäytön näkökulmasta: kotilataus vähentää tarvetta
    arki_henkilominuutteja = sum(muutos[koskee] * arkiriippuvaiset[koskee]),
    # Kynnysmittari: kuinka moni siirtyy kipurajan yli
    yli_kipurajan = sum(vakiluku[!is.na(muutos) &
                                   nyky <= kipuraja_min &
                                   uusi_min > kipuraja_min]),
    # Kuinka moni menettää yhteyden kokonaan
    katkeaa_asukkaita = sum(vakiluku[katkeaa]),
    # Pahin yksittäinen alue
    pahin_alue_min = suppressWarnings(max(muutos, na.rm = TRUE)),
    # Koko maan keskiarvo kuljetaan mukana vain vertailua varten
    keskikasvu_min = weighted.mean(muutos, vakiluku, na.rm = TRUE)
  )
}) |>
  mutate(pahin_alue_min = if_else(is.finite(pahin_alue_min),
                                  pahin_alue_min, NA_real_)) |>
  left_join(select(hpc, avain, nimi, kunta, op_nimi, max_kw, pistokkeita,
                   lat, lon), by = "avain")

stopifnot(
  "Poistolaskenta tuotti negatiivisia muutoksia" =
    all(poistovaikutus$kasvu_koskeville >= -1e-9, na.rm = TRUE),
  "Poistolaskenta epäonnistui" = nrow(poistovaikutus) == nrow(hpc),
  "Kynnysmittari on nolla kaikilla – valitse toinen kipuraja" =
    sum(poistovaikutus$yli_kipurajan) > 0
)

# Kuinka paljon laimennus muuttaa kuvaa? Tämä luku menee tekstiin.
laimennuskerroin <- poistovaikutus |>
  slice_max(henkilominuutteja, n = 1) |>
  transmute(kerroin = kasvu_koskeville / pmax(keskikasvu_min, 1e-9)) |>
  pull(kerroin)

jakauman_muoto <- poistovaikutus |>
  summarise(
    mediaani = median(kasvu_koskeville, na.rm = TRUE),
    maksimi = max(kasvu_koskeville, na.rm = TRUE),
    ei_ketaan = mean(asukkaita_koskee == 0),
    top10_osuus = sum(sort(henkilominuutteja, decreasing = TRUE)[1:10],
                      na.rm = TRUE) / sum(henkilominuutteja, na.rm = TRUE)
  )

Miksi koko maan keskiarvo ei kelpaa tähän

Ilmeisin tapa mitata aseman kriittisyyttä olisi laskea, kuinka paljon suomalaisten keskimääräinen matka lähimmälle laturille pitenisi. Kokeilin sitä ensin, ja tulos oli käyttökelvoton.

Syy on aritmetiikassa. Maan kriittisinkin asema koskettaa muutamaa tuhatta ihmistä. Kun heidän kokemansa kymmenien minuuttien lisäys jaetaan viiden ja puolen miljoonan asukkaan kesken — joista valtaosa ei huomaisi mitään — jäljelle jää muutama sekunti.

Kriittisimmän aseman kohdalla ero on 536-kertainen: se, mitä se tarkoittaa asianosaisille, on tuhatkertainen siihen nähden, miltä se näyttää kansallisessa keskiarvossa.

Luku ei olisi ollut väärin. Se olisi ollut tosi ja merkityksetön — ja juuri siksi vaarallinen, koska se olisi antanut ymmärtää ettei yhdelläkään asemalla ole väliä.

Mittaan siksi kolmea asiaa erikseen: keitä aseman katoaminen koskee, kuinka paljon se koskee juuri heitä, ja kuinka moni siirtyy sen myötä kohtuullisen matkan päästä kohtuuttoman taakse.

Asemien kriittisyyden jakauma kahdella eri mittarilla.

Miten kuvaa luetaan. Molemmat paneelit kuvaavat täsmälleen samaa laskentaa. Ainoa ero on se, kenen kesken vaikutus jaetaan.

Ylempi harmaa paneeli jakaa sen koko Suomen väestölle, ja silloin akselin yksikkönä on sekunti. Alempi jakaa sen vain niille, joiden matka oikeasti pitenee, ja silloin yksikkönä on minuutti.

Alemmassa paneelissa valtaosa asemista on edelleen vasemmassa laidassa. Se ei tarkoita että ne olisivat tarpeettomia — se tarkoittaa, että niiden vieressä on toinen asema. Jos sellainen asema katoaa, käyttäjä ajaa naapuriin eikä kukaan huomaa mitään.

Oikeassa hännässä on asemia, joiden katoaminen tarkoittaisi asianosaisille kymmenien minuuttien lisämatkaa. Ne ovat tämän osan kohde.

Kymmenen kriittisintä asemaa vastaa 23% kaikkien asemien yhteenlasketusta kokonaisvaikutuksesta.

Riskikartta

Latausasemien kriittisyys: kuinka paljon koko maan saavutettavuus heikkenisi, jos asema katoaisi.

Miten karttaa luetaan. Jokainen piste on suurtehulatausasema.

Pisteen väri kertoo, kuinka paljon matka lähimmälle laturille pitenisi niillä ihmisillä, joita aseman katoaminen koskee. Sininen tarkoittaa muutamaa minuuttia, punainen puolta tuntia tai enemmän.

Pisteen koko kertoo, kuinka moni ihminen on asianosainen.

Nämä kaksi eivät kulje käsi kädessä, ja siinä on kartan koko viesti. Pieni punainen piste on asema, jonka katoaminen olisi harvoille katastrofi. Suuri sininen piste on asema, jonka katoaminen olisi monille pieni harmi. Kumpaa pidetään pahempana, on arvovalinta — mutta se on valinta, joka pitää tehdä tietoisesti eikä mittarin sivutuotteena.

Kartta ei kerro, mitkä asemat ovat vilkkaimpia tai suurimpia. Se kertoo, mitkä ovat korvaamattomimpia — ja nämä kaksi ovat eri asioita. Vilkkain asema on siellä missä on paljon ihmisiä, ja siellä on yleensä myös vaihtoehtoja.

Kriittisimmät latausasemat.

Miten kuvaa luetaan. Vasen paneeli kertoo, kuinka paljon matka pitenisi niillä ihmisillä, joita aseman katoaminen koskee. Oikea kertoo, kuinka monta heitä on.

Asemat on järjestetty näiden tulon mukaan, eli kokonaisvaikutuksen. Paneelien järjestys ei ole sama, ja se on tarkoituksellista: osa asemista nousee listalle siksi että vaikutus on suuri, osa siksi että asianosaisia on paljon.

Sama asema ei ole yhtä tärkeä kaikille

Tähän asti olen mitannut yhtä asiaa: kuinka paljon matka lähimmälle suurtehulaturille pitenee, jos asema katoaa. Mittari olettaa hiljaisesti, että kaikki tarvitsevat sitä asemaa samalla tavalla.

He eivät tarvitse. Suurtehulaturia käytetään kahteen täysin eri tarkoitukseen, ja niiden kriittisyys määräytyy eri tavalla.

Arkilataus. Asukas, jolla ei ole omaa latauspaikkaa, käy lataamassa autonsa lähimmällä julkisella laturilla samaan tapaan kuin ennen käytiin bensa-asemalla. Hänelle lähin asema on arkinen välttämättömyys. Omakotitalossa asuva, joka lataa autonsa yöllä kotona, ei tätä asemaa tarvitse juuri koskaan.

Matkalataus. Pitkällä matkalla auto on ladattava jossain matkan varrella. Tämä ei riipu lainkaan siitä, missä matkalainen asuu tai onko hänellä kotona latauspistettä. Helsingistä Rovaniemelle ajava tarvitsee aseman kilometrillä kolmesataa myös silloin, kun hän on lähtenyt liikkeelle täydellä akulla omakotitalon autotallista.

Näistä ensimmäinen on herkkä asumismuodolle, jälkimmäinen ei ole sille lainkaan herkkä. Siksi ne on laskettava erikseen.

Arjen kriittisyys: ketä lähin asema oikeasti palvelee

Tämän sarjan aiemmassa osassa arvioitiin kotilatausmahdollisuutta pientaloasumisen osuudesta. Käytän samaa arviota tässä: alueen asukkaista julkisesta verkosta arjessa riippuvaisiksi lasketaan kerrostaloasumisen osuutta vastaava osa.

Koko maassa tämä tarkoittaa noin 46% väestöstä. Loput lataavat pääosin kotona.

Code
arkivertailu <- poistovaikutus |>
  mutate(
    arjen_paino = if_else(henkilominuutteja > 0,
                          arki_henkilominuutteja / henkilominuutteja,
                          NA_real_)
  )

# Järjestyksen muutos: kuinka moni kärkiasemista vaihtuu, kun
# kotilataus otetaan huomioon?
karki_kaikki <- arkivertailu |> slice_max(henkilominuutteja, n = 20) |> pull(avain)
karki_arki   <- arkivertailu |> slice_max(arki_henkilominuutteja, n = 20) |> pull(avain)
paallekkaisyys <- length(intersect(karki_kaikki, karki_arki))

kor_arki <- cor(arkivertailu$henkilominuutteja,
                arkivertailu$arki_henkilominuutteja,
                method = "spearman", use = "complete.obs")

Kahdenkymmenen kärjestä 9 on sama molemmilla mittareilla, ja järjestyskorrelaatio on 0,96.

Kotilatauksen huomioiminen ei siis mullista järjestystä, ja syy on ymmärrettävä: asemat ovat siellä missä on asutusta, ja asutuksen rakenne vaihtelee vähemmän kuin asemien harvuus. Mutta se siirtää painopistettä taajamiin päin, koska siellä kerrostaloasumisen osuus on suurin.

Kuinka suuri osa aseman vaikutuksesta kohdistuu arjessa julkisesta verkosta riippuvaisiin.

Miten kuvaa luetaan. Vaaka-akselilla on aseman kriittisyys asianosaisille, pystyakselilla se, kuinka suuri osa asianosaisista on vailla kotilatausta. Punainen katkoviiva on koko maan taso.

Viivan alapuolella olevat asemat palvelevat keskimääräistä enemmän omakotitaloasujia, jotka lataavat pääosin kotona. Viivan yläpuolella olevat palvelevat kerrostaloasujia, joille julkinen verkko on ainoa vaihtoehto.

Kuvassa näkyy selvä kaltevuus: mitä kriittisempi asema on etäisyysmielessä, sitä todennäköisemmin sen lähialueella asutaan pientaloissa. Se on looginen seuraus siitä, että harvaan asutuilla alueilla sekä asemia että kerrostaloja on vähän.

Tästä seuraa epämiellyttävä johtopäätös. Jos aseman tärkeyttä mitattaisiin pelkästään arkikäytöllä, syrjäseutujen asemat putoaisivat listan hännille — ei siksi että niitä ei tarvittaisi, vaan siksi että niiden lähialueella asutaan omakotitaloissa.

Arkimittari yksinään siis siirtäisi tuen kaupunkeihin ja jättäisi harvaan asutut alueet ilman. Sitä varten tarvitaan toinen mittari.

Matkan kriittisyys: milloin asema on ketjun lenkki

Arkimittari ei tavoita sitä tilannetta, jonka vuoksi syrjäinen asema on usein korvaamaton. Asema voi olla lähes tyhjä ja silti välttämätön, jos se on ainoa latausmahdollisuus kahden kaukana toisistaan olevan aseman välissä.

Tällöin kyse ei ole siitä, kuka asuu lähellä. Kyse on siitä, että ilman tuota asemaa jokin väli kasvaa pidemmäksi kuin akku kestää — ja se koskee jokaista ohi ajavaa riippumatta siitä, missä hän asuu.

Mittaan tämän kysymällä: jos asema poistetaan, kuinka pitkäksi kasvaa se väli, joka sen tilalle jää?

Code
matriisi_asemat_path <- file.path(data_dir, "matkamatriisi.qs")
stopifnot("Asemien matkamatriisi puuttuu – aja edellinen osa ensin" =
            file.exists(matriisi_asemat_path))

mm <- qs2::qs_read(matriisi_asemat_path)
D_kaikki <- mm$matkat

yhteiset <- intersect(rownames(D_kaikki), hpc$avain)
D <- D_kaikki[yhteiset, yhteiset]

stopifnot(
  "Matkamatriisi ei kata asemia" = length(yhteiset) > 50,
  "Matriisi ei ole neliö" = nrow(D) == ncol(D)
)

# Talvinen pienen akun kantama: väli, jota pidetään liian pitkänä
kantamaraja_km <- 150

# Jokaiselle asemalle: kuinka pitkäksi lähimmän naapurin matka kasvaa
# muilla asemilla, jos tämä asema poistetaan. Jos jonkin aseman lähin
# naapuri hyppää kantamarajan yli, poistettu asema oli ketjun lenkki.
naapurietaisyys <- function(Dm) {
  diag(Dm) <- Inf
  apply(Dm, 1, \(r) min(r, na.rm = TRUE))
}

nyky_naapuri <- naapurietaisyys(D)

ketjulenkki <- map_dfr(seq_len(nrow(D)), function(j) {
  D2 <- D[-j, -j, drop = FALSE]
  uusi <- naapurietaisyys(D2)
  vanha <- nyky_naapuri[-j]

  kasvu <- uusi - vanha
  ylittaa <- is.finite(uusi) & vanha <= kantamaraja_km & uusi > kantamaraja_km

  tibble(
    avain = rownames(D)[j],
    pisin_vali_km = suppressWarnings(max(uusi[is.finite(uusi)], na.rm = TRUE)),
    vali_kasvu_km = suppressWarnings(max(kasvu[is.finite(kasvu)], na.rm = TRUE)),
    rikkoo_ketjun = any(ylittaa)
  )
}) |>
  mutate(across(c(pisin_vali_km, vali_kasvu_km),
                \(x) if_else(is.finite(x), x, NA_real_)))

stopifnot(
  "Ketjulaskenta epäonnistui" = nrow(ketjulenkki) == nrow(D),
  "Välin kasvu on negatiivinen" =
    all(ketjulenkki$vali_kasvu_km >= -1e-9, na.rm = TRUE)
)

n_ketjulenkkeja <- sum(ketjulenkki$rikkoo_ketjun, na.rm = TRUE)

kriittisyys <- poistovaikutus |>
  left_join(ketjulenkki, by = "avain")

Asemia, joiden poistuminen kasvattaa jonkin välin yli 150 kilometrin, on 0.

Nämä ovat matkalatauksen kannalta kriittisiä riippumatta siitä, kuka niiden lähellä asuu. Raja 150 kilometriä vastaa talvista pienen akun kantamaa; kesällä suurella akulla sama väli olisi ongelmaton.

Arjen kriittisyys ja matkan kriittisyys samassa kuvassa.

Miten kuvaa luetaan. Vaaka-akselilla on arjen kriittisyys: kuinka paljon aseman katoaminen haittaisi niitä lähialueen asukkaita, joilla ei ole kotilatausmahdollisuutta. Akseli on logaritminen, koska arvot vaihtelevat tuhansiin.

Pystyakselilla on matkan kriittisyys: kuinka paljon pisin väli kasvaa, jos asema katoaa. Punaiset pisteet ovat asemia, joiden poistuminen kasvattaa välin yli talvisen kantaman.

Kuvan neljä lohkoa tarkoittavat eri asioita.

Oikea alakulma on kaupunkiasema: paljon kotilatausta vailla olevia käyttäjiä, mutta naapurissa on toinen asema. Jos se katoaa, moni kokee pienen harmin.

Vasen yläkulma on juuri se tapaus, jota arkimittari ei näe. Lähellä ei asu juuri ketään ilman kotilatausta — mutta asema on ketjun ainoa lenkki, ja sen katoaminen katkaisee matkalatausreitin kaikilta ohi ajavilta.

Oikea yläkulma olisi pahin mahdollinen: paljon arkikäyttäjiä ja ketjun lenkki. Niitä on vähän, mikä on hyvä uutinen.

Vasen alakulma on asema, jonka katoamista ei huomaisi juuri kukaan.

Tämä on osan tärkein korjaus. Yksi kriittisyysluku ei riitä, koska latausasemalla on kaksi eri tehtävää eivätkä ne mene samoihin paikkoihin. Kaupunkiasema on tärkeä siksi että sen käyttäjillä ei ole vaihtoehtoa kotona; syrjäinen asema on tärkeä siksi että sen käyttäjillä ei ole vaihtoehtoa matkalla. Tuki, joka mittaa vain toista, kohdistuu väärin.

Kriittisyys ei ole sama kuin koko

Code
kor_koko <- cor.test(poistovaikutus$henkilominuutteja,
                     poistovaikutus$pistokkeita,
                     method = "spearman", exact = FALSE)

kor_teho <- cor.test(poistovaikutus$henkilominuutteja,
                     poistovaikutus$max_kw,
                     method = "spearman", exact = FALSE)

# Operaattorivertailu
isot_op <- poistovaikutus |> count(op_nimi) |> filter(n >= 8) |> pull(op_nimi)
op_data <- poistovaikutus |> filter(op_nimi %in% isot_op)

kw_testi <- kruskal.test(henkilominuutteja ~ op_nimi, data = op_data)
n_tot <- nrow(op_data)
epsilon2 <- unname(kw_testi$statistic) / ((n_tot^2 - 1) / (n_tot + 1))

Kriittisyyden ja pistokemäärän järjestyskorrelaatio on -0,136, ja kriittisyyden ja tehon -0,127.

Miksi järjestyskorrelaatio. Kriittisyysjakauma on erittäin vino: valtaosa asemista on nollan tuntumassa ja muutama kaukana ylhäällä. Tavallinen korrelaatiokerroin olettaa suunnilleen symmetrisen jakauman ja reagoi voimakkaasti yksittäisiin ääriarvoihin, joita tässä on paljon. Järjestyskorrelaatio käyttää vain sijalukuja eikä oleta jakauman muodosta mitään.

Aseman koko ja sen kriittisyys.

Miten kuvaa luetaan. Vaaka-akselilla on aseman koko pistokemäärällä mitattuna, pystyakselilla sen kriittisyys verkoston kannalta. Jos nämä kulkisivat käsi kädessä, pisteet asettuisivat nousevalle suoralle.

Ne eivät asetu. Kriittisimmät asemat löytyvät kuvan vasemmasta laidasta eli pienten asemien joukosta. Syy on maantieteellinen: pieni asema on pieni koska sen ympärillä ei ole paljon ihmisiä, ja juuri siksi sen ympärillä ei ole myöskään muita asemia.

Tällä on suora seuraus julkiselle tuelle. Jos tukea kohdennetaan aseman koon, käyttöasteen tai investoinnin suuruuden perusteella, se ohjautuu asemille, joiden katoamista kukaan ei huomaisi. Verkoston kestävyyden kannalta olennaiset asemat ovat pieniä, syrjäisiä ja liiketaloudellisesti heikoimpia.

NoteFaktalaatikko: miksi verkot kestävät satunnaisvahinkoa mutta eivät kohdennettua

Verkostoteoriassa on tunnettu tulos, joka koskee lähes kaikkia todellisia verkkoja: sähköverkkoja, internetiä, lentoliikennettä, ekosysteemejä.

Näissä verkoissa solmujen tärkeys on erittäin epätasaisesti jakautunut. Valtaosa solmuista on merkityksettömiä ja muutama pitää verkkoa kasassa. Sama rakenne näkyy tämän osan ensimmäisessä kuvassa.

Rakenteesta seuraa kaksi vastakkaista ominaisuutta. Verkko kestää poikkeuksellisen hyvin satunnaisia vaurioita: jos solmuja katoaa umpimähkään, osumat kohdistuvat lähes aina merkityksettömiin solmuihin eikä mitään tapahdu. Mutta verkko on poikkeuksellisen haavoittuvainen kohdennetulle vahingolle: jos solmuja poistetaan tärkeysjärjestyksessä, verkko hajoaa nopeasti.

Ilmiö tunnetaan nimellä robust yet fragile, ja se on yksi verkostotutkimuksen keskeisimmistä havainnoista.

Mitä tästä seuraa latausverkolle. Yksittäisen aseman satunnainen rikkoutuminen ei ole ongelma, ja siksi arki näyttää sujuvan hyvin. Se ei kerro mitään siitä, miten verkko kestäisi häiriön, joka ei ole satunnainen — kuten yhden operaattorin taustajärjestelmän kaatumista, sähkökatkoa laajalla alueella tai poikkeuksellista kysyntähuippua samaan aikaan samoilla teillä.

Tätä eroa testaan seuraavassa luvussa numeerisesti.

Vaihtoehtoiset skenaariot: satunnainen vastaan kohdennettu

Code
# Poistetaan asemia yksi kerrallaan kahdessa järjestyksessä ja
# seurataan, miten saavutettavuus heikkenee.
poista_ketju <- function(jarjestys, askeleet = 40) {
  jaljella <- seq_len(ncol(ajat_k))
  tulos <- vector("list", askeleet)

  for (s in seq_len(askeleet)) {
    poistettava <- jarjestys[s]
    jaljella <- setdiff(jaljella, poistettava)
    m <- apply(ajat_k[, jaljella, drop = FALSE], 1, \(r) min(r, na.rm = TRUE))
    kelpo_r <- is.finite(m)

    tulos[[s]] <- tibble(
      poistettu = s,
      keskiaika = weighted.mean(m[kelpo_r], vakiluku[kelpo_r]),
      ilman_yhteytta = sum(vakiluku[!kelpo_r]) / sum(vakiluku)
    )
  }
  bind_rows(tulos)
}

# Kohdennettu: kriittisimmät ensin
jarjestys_kohdennettu <- order(poistovaikutus$henkilominuutteja,
                               decreasing = TRUE, na.last = TRUE)

# Satunnainen: keskiarvo useasta vedosta, jotta yksittäinen
# onnekas tai epäonnekas järjestys ei ohjaa tulosta
satunnaiset <- map_dfr(1:20, function(k) {
  poista_ketju(sample(ncol(ajat_k))) |> mutate(veto = k)
}) |>
  group_by(poistettu) |>
  summarise(keskiaika = mean(keskiaika),
            ilman_yhteytta = mean(ilman_yhteytta),
            .groups = "drop") |>
  mutate(tapa = "Satunnainen häiriö")

kohdennettu <- poista_ketju(jarjestys_kohdennettu) |>
  mutate(tapa = "Kohdennettu häiriö")

vertailu <- bind_rows(satunnaiset, kohdennettu)

stopifnot(
  "Ketjulaskenta epäonnistui" = nrow(vertailu) > 0,
  "Keskiaika laskee poistojen myötä" =
    all(diff(kohdennettu$keskiaika) >= -1e-6)
)

ero_40 <- vertailu |>
  filter(poistettu == max(poistettu)) |>
  select(tapa, keskiaika)

# Onko kokonaisuus enemmän kuin osiensa summa? Verrataan yksittäispoistojen
# summaa siihen, mitä samojen asemien yhtäaikainen poisto tekee.
n_askelta <- max(vertailu$poistettu)

summa_erikseen <- poistovaikutus |>
  slice_max(henkilominuutteja, n = n_askelta) |>
  summarise(s = sum(keskikasvu_min, na.rm = TRUE)) |>
  pull(s)

yhdessa <- kohdennettu |>
  filter(poistettu == n_askelta) |>
  pull(keskiaika) - nyky_keskiaika

superadditiivisuus <- yhdessa / summa_erikseen

stopifnot(
  "Yhtäaikainen poisto on pienempi kuin erillisten summa – tarkista järjestys" =
    superadditiivisuus >= 0.95
)

Saavutettavuuden heikkeneminen, kun asemia poistetaan kahdessa eri järjestyksessä.

Miten kuvaa luetaan. Vaaka-akselilla on poistettujen asemien määrä, pystyakselilla suomalaisten keskimääräinen matka lähimmälle suurtehulaturille.

Turkoosi käyrä kuvaa satunnaista häiriötä: asemia katoaa umpimähkään. Punainen kuvaa kohdennettua: kriittisimmät poistuvat ensin.

Tässä kuvassa pystyakseli on koko maan keskiarvo, vaikka edellä juuri totesin sen huonoksi mittariksi. Ero on siinä, mihin lukua käytetään. Yksittäisen aseman arvon kuvaamiseen se ei kelpaa, koska laimennus peittää vaikutuksen. Kahden skenaarion vertailuun se kelpaa hyvin, koska molemmat lasketaan samalla nimittäjällä ja kiinnostavaa on käyrien välinen ero, ei niiden korkeus.

Kokonaisuus on enemmän kuin osiensa summa

Kuvassa on yksityiskohta, joka on helppo ohittaa mutta joka on tämän osan kiinnostavin yksittäinen tulos.

Jos lasken yhteen 40 kriittisimmän aseman yksittäiset vaikutukset — siis sen, mitä kukin niistä tekee erikseen poistettuna — saan selvästi pienemmän luvun kuin se, mitä niiden yhtäaikainen poistuminen tekee. Suhde on noin 1,07-kertainen.

Syy on ymmärrettävä kun sen sanoo ääneen. Kun ensimmäinen asema poistetaan, sen käyttäjät siirtyvät naapuriasemalle. Kun myös naapuri poistetaan, he siirtyvät jo kauemmas — ja tuon toisen aseman vaikutus on silloin suurempi kuin mitä se oli yksin mitattuna, koska pakotie oli jo tukittu.

Ilmiötä kutsutaan superadditiivisuudeksi, ja sillä on suora käytännön seuraus. Riskilista, joka on laadittu poistamalla yksi kohde kerrallaan, aliarvioi systemaattisesti sen, mitä useampi samanaikainen häiriö tekisi. Juuri niin riskilistat kuitenkin lähes aina laaditaan — myös tämän osan riskikartta on sellainen.

Kerron tämän siksi, että tiedän oman menetelmäni rajan. Kartta kuvaa oikein sitä, mikä yksittäinen asema on korvaamattomin. Se ei kuvaa oikein sitä, mitä tapahtuu päivänä jona useampi asia menee rikki yhtä aikaa — ja se on poikkeustilanteen määritelmä.

Ero on suuri, ja se on tämän osan tärkein tulos. Verkko kestää satunnaista vahinkoa hyvin ja kohdennettua huonosti. Se ei ole latausverkon erityispiirre vaan yleinen ominaisuus, mutta sen suuruus on tässä mitattu.

Käytännön seuraus on kaksijakoinen. Hyvä uutinen: yksittäiset viat eivät ole ongelma, ja arki sujuu. Huono uutinen: mittarit, jotka seuraavat arkea, eivät kerro mitään verkon kestävyydestä poikkeustilanteessa.

Kuinka monta asemaa erottaa Lapin?

Kestävyyttä voi kysyä myös toisin. Sen sijaan että poistettaisiin asemia tärkeysjärjestyksessä, voidaan kysyä: kuinka monta asemaa pitäisi vähintään poistaa, jotta jokin alue irtoaisi muusta verkosta?

Tämä on graafiteorian minimileikkaus. Se etsii pienimmän joukon solmuja, joiden poistaminen katkaisee yhteyden kahden pisteen välillä.

Code
# Asemien välinen matkamatriisi D on luettu jo edellä matkan
# kriittisyyttä varten; käytetään samaa.
hpc_v <- hpc |> filter(avain %in% yhteiset) |>
  arrange(match(avain, yhteiset))

stopifnot("Matriisin ja asemataulun järjestys ei täsmää" =
            all(rownames(D) == hpc_v$avain))

# Kaari kahden aseman välille, jos ne ovat toistensa naapureita eikä
# välissä ole kolmatta asemaa.
rng_matriisi <- function(Dm, raja) {
  n <- nrow(Dm)
  A <- (Dm <= raja) & is.finite(Dm)
  diag(A) <- FALSE
  for (k in seq_len(n)) {
    M <- pmax(matrix(Dm[, k], n, n), matrix(Dm[k, ], n, n, byrow = TRUE))
    A[is.finite(M) & M < Dm] <- FALSE
  }
  diag(A) <- FALSE
  A
}

g <- graph_from_adjacency_matrix(rng_matriisi(D, 300), mode = "undirected")
V(g)$avain <- hpc_v$avain
V(g)$lat <- hpc_v$lat
V(g)$kunta <- hpc_v$kunta

# Eteläisin ja pohjoisin asema: näiden välisen yhteyden katkaiseminen
# irrottaisi pohjoisen etelästä.
etela <- which.min(V(g)$lat)
pohjoinen <- which.max(V(g)$lat)

leikkaus <- min_cut(g, source = etela, target = pohjoinen,
                    value.only = FALSE)

leikkaus_koko <- leikkaus$value

stopifnot(
  "Minimileikkaus epäonnistui" = is.finite(leikkaus_koko),
  "Leikkaus on epäuskottavan suuri" = leikkaus_koko < 20
)

Etelän ja pohjoisen välinen yhteys katkeaisi, jos 1 yhteyttä poistuisi verkosta.

Luku on pienempi kuin useimmat arvaisivat. Se ei tarkoita, että pohjoiseen ei pääsisi ajamaan — se tarkoittaa, ettei sinne pääsisi suurtehulatureiden ketjua pitkin ilman että jokin väli ylittää kolmesataa kilometriä.

Tulos on rakenteellinen ja seuraa maantieteestä: Suomi on kapea maa, ja pohjoiseen johtaa käytännössä muutama päätie. Latausverkko noudattaa teitä, joten sen rakenne perii tieverkon rakenteen.

ImportantMitä tämä analyysi ei ota huomioon

Asemat eivät katoa vaan menevät epäkuntoon. Poistosimulaatio olettaa aseman katoavan kokonaan. Todellisuudessa yleisin häiriö on osittainen: yksi laturi kolmesta ei toimi, jono on pitkä, tai maksupääte kaatuu. Näiden vaikutus riippuu käyttöasteesta, jota ei ole julkisesti saatavilla.

Hitaammat laturit puuttuvat. Tarkastelu koskee vain suurtehulatureita. Häiriötilanteessa autoilija voi käyttää hitaampaa laturia, jos aikaa on. Kartta kuvaa siis pikalatausverkon kestävyyttä, ei liikkumisen mahdottomuutta.

Ajoajat ovat systemaattisesti alakanttiin, kaupungeissa pahiten. Ajoaika lasketaan nopeusrajoituksista, eikä laskenta tunne liikennevaloja, risteysviiveitä eikä ruuhkia. Maantiellä virhe on pieni, mutta kaupungissa se on suuri — siellä matka-ajasta merkittävä osa kuluu juuri niihin asioihin, joita malli ei tunne.

Tämä näkyy suoraan siinä, että nykytilan keskimääräinen matka lähimmälle suurtehulaturille on 5.8 minuuttia. Luku on epäuskottavan pieni jokaiselle, joka on joskus ajanut kaupungissa. Se on oikein laskettu mutta kuvaa esteetöntä ajoa, ei todellista.

Vertailuihin tämä ei vaikuta, koska virhe on samansuuntainen kaikkialla. Yksittäistä lukua ei kuitenkaan pidä lukea todellisena matka-aikana.

Rekisteri on epätäydellinen. Sarjan ensimmäisessä osassa arvioitiin, että osa asemista puuttuu rekisteristä kokonaan. Jos puuttuvat asemat ovat siellä missä muutkin, riskiarvio on hieman yläkanttiin. Jos ne ovat syrjässä, arvio on liian matala. En tiedä kumpi pätee.

Kriittisyys on nykyhetken ominaisuus. Uusi asema kriittisen aseman viereen poistaa kriittisyyden kokonaan. Kartta kuvaa siis tilannetta, ei kohtaloa — ja juuri siksi se on hyödyllinen.

Mitä jää käteen

Useimpien asemien katoamista ei huomaisi kukaan. Se ei tee niistä tarpeettomia; se tarkoittaa että niillä on naapuri.

Nimittäjä ratkaisee, näyttääkö mikään miltään. Koko maan keskiarvona kriittisimmänkin aseman katoaminen on muutaman sekunnin asia. Asianosaisille se on kymmeniä minuutteja. Sama laskenta, eri nimittäjä, tuhatkertainen ero.

Latausasemalla on kaksi eri tehtävää, ja ne eivät ole samoissa paikoissa. Kaupunkiasema on korvaamaton siksi, että sen käyttäjillä ei ole latausmahdollisuutta kotona. Syrjäinen asema on korvaamaton siksi, että sen käyttäjillä ei ole vaihtoehtoa matkan varrella. Mittari, joka tunnistaa vain toisen, kohdentaa tuen väärin.

Riskilistat aliarvioivat yhtäaikaiset häiriöt. Yksi kerrallaan poistaen mitattu kriittisyys ei summaudu: yhdessä poistetut asemat tekevät enemmän vahinkoa kuin erikseen mitattuna.

Kriittisyys ei seuraa kokoa. Kriittisimmät asemat ovat pieniä ja syrjäisiä — eli juuri niitä, joita markkinaehtoinen rakentaminen tuottaa vähiten ja joiden kannattavuus on heikoin.

Verkko kestää satunnaista vahinkoa ja hajoaa kohdennetusta. Arjen mittarit kertovat ensimmäisestä eivätkä mitään toisesta.

Pohjoisen yhteys nojaa harvoihin väleihin. Se on seurausta maantieteestä, ei suunnitteluvirheestä — mutta se on tiedettävä.

Seuraavassa osassa siirryn rakenteesta ajankohtaan. Verkko, joka riittää keskiviikkona marraskuussa, ei välttämättä riitä juhannusaattona — ja kesämökkien sijainti kertoo, missä se ruuhkautuu.


Mitä tästä on hyötyä yrityksellesi

Aja poistotesti omalle infrastruktuurillesi. Tämän osan koko menetelmä on yksi silmukka: poista yksi solmu, mittaa lopputulos, palauta, siirry seuraavaan. Sitä voi soveltaa mihin tahansa, mikä on mallinnettavissa verkkona — toimittajiin, järjestelmiin, avainhenkilöihin, toimipisteisiin. Vastaus kysymykseen “mitä tapahtuu jos tämä katoaa” on laskettavissa, ei arvattavissa.

Älä priorisoi kokoa, priorisoi korvaamattomuutta. Suurin toimittaja ei ole kriittisin. Kriittisin on se, jolle ei ole vaihtoehtoa. Nämä ovat lähes aina eri toimijoita, ja ero näkyy vasta kun sen laskee.

Muista, että arki ei ennusta poikkeustilaa. Verkko, joka kestää satunnaisvahinkoa erinomaisesti, voi romahtaa kohdennetusta. Jos varautumissuunnitelma nojaa siihen, että viime vuonna ei sattunut mitään, se mittaa satunnaista häiriötä eikä kerro mitään järjestelmällisestä.

Tämä on suoraan DORA:n ja NIS2:n logiikka: valvoja ei kysy, onko teillä sattunut häiriöitä, vaan onko teillä tunnistettu mitkä toiminnot kaatuvat ensin ja mitä siitä seuraa.

Kysy, onko sama resurssi kahdessa eri käytössä. Latausasema osoittautui kahdeksi eri asiaksi: arjen peruspalveluksi niille joilla ei ole vaihtoehtoa kotona, ja matkaketjun lenkiksi kaikille ohi ajaville. Yksi kriittisyysluku ei voinut kuvata molempia.

Sama pätee yllättävän moneen asiaan organisaatiossa. Järjestelmä, jota käytetään sekä päivittäiseen rutiiniin että kerran kuussa tapahtuvaan tilinpäätökseen, on kriittinen kahdesta eri syystä ja eri aikoina. Avainhenkilö, joka hoitaa arjen työt ja on lisäksi ainoa joka osaa yhden harvinaisen prosessin, on korvattavissa ensimmäisessä roolissa ja korvaamaton toisessa. Jos kriittisyys lasketaan yhtenä lukuna, toinen rooli katoaa näkyvistä — ja yleensä se joka katoaa on se harvinainen, koska se on pienempi volyymiltaan.

Tarkista riskiarviosi nimittäjä. Jos riskin suuruus lasketaan jakamalla vaikutus koko organisaatiolle, koko asiakaskunnalle tai koko liikevaihdolle, jokainen yksittäinen riski näyttää pieneltä. Se ei ole laskuvirhe vaan näkökulmavirhe, ja se johtaa järjestelmällisesti siihen ettei mitään priorisoida. Kysy aina erikseen: keitä tämä koskee, kuinka paljon se koskee juuri heitä, ja kuinka moni ylittää sietokynnyksen.

Älä oleta riskien summautuvan. Yksi kerrallaan arvioidut riskit ovat yhdessä pahempia kuin erikseen, koska varajärjestelyt ovat usein samoja. Jos palvelin A kaatuu, kuorma siirtyy palvelimelle B; jos molemmat kaatuvat, vaikutus on enemmän kuin kaksinkertainen. Sama koskee avainhenkilöitä, toimittajia ja toimipisteitä. Riskirekisteri, jossa jokainen rivi on arvioitu yksinään, kuvaa normaalipäivää eikä sitä päivää jota varten se on tehty.

Erota “ei ole tapahtunut” ja “ei voi tapahtua”. Riskikartta on todennäköisyyksistä riippumaton: se kertoo mitä seuraisi, ei kuinka todennäköistä se on. Molempia tarvitaan, mutta ne on laskettava erikseen. Seurausten laskeminen on usein helpompaa kuin todennäköisyyden arviointi — ja silti se jätetään useammin tekemättä.

Ja tee kartta, älä listaa. Tämän osan tulos olisi voitu esittää taulukkona viidestätoista tärkeimmästä asemasta. Kartta kertoo saman ja lisäksi sen, missä ne ovat ja miksi. Kun analyysin pitää muuttaa jonkun mieltä, esitystapa ratkaisee yhtä paljon kuin sisältö.

Jos organisaatiossasi ei ole laskettu, mikä hajoaa ensin ja mitä siitä seuraa, tai jos kriittisyys on määritelty kokouksessa eikä mitattu, siinä on työtä odottamassa. Teen tätä vuokrattavana Head of Datana ja projektikohtaisesti — hinnasto ja yhteystiedot löytyvät sivustolta.


Aineistot: OpenStreetMap (© OpenStreetMap-osallistujat, ODbL 1.0), Fintraffic AFIR / Digitraffic, Tilastokeskuksen Paavo-aineisto, Eurostat GISCO. Koodi on kokonaisuudessaan tässä postauksessa. Maailma on jakauma.