---
title: "Mitä lakialoitteille todella tapahtuu?"
subtitle: "Eduskunta jakaumana, osa 9: aloitteen kohtalo"
description: >
Lähdimme ennustamaan, mikä saa lakialoitteen läpi. Data pakotti vaihtamaan
kysymyksen: lähes yksikään ei etene omana esityksenään. Tämä osa kertoo, mitä
lakialoitteille oikeasti tapahtuu — ja miksi ne ovat useammin signaali kuin
väylä lakiin.
date: 2026-08-27
author: "Kristian Vepsäläinen"
categories: [eduskunta, avoin data, jakaumat, lakialoitteet]
format:
html:
toc: true
toc-title: "Sisällys"
code-fold: true
code-summary: "Näytä koodi"
execute: { warning: false, message: false, echo: true }
---
> **Sarjan idea.** Tässä osassa tapahtui jotain, mikä on itse sarjan opetus:
> aioimme rakentaa ennustemallin lakialoitteen läpimenolle, mutta data osoitti,
> että läpimeno on niin harvinaista, ettei mallia kannata rakentaa. Kun uusi tieto
> muuttaa kysymyksen, kysymys on vaihdettava — ei väännettävä dataa vastaamaan
> vanhaan.
## Uutiskoukku: kysymys, joka piti vaihtaa
Alkuperäinen kysymys oli houkutteleva: *mikä ennustaa, meneekö lakialoite läpi?*
Mutta kun katsoimme dataa, läpimenneitä oli häviävän vähän — niin vähän, ettei
"ennustaminen" ollut mielekästä. Se ei ollut datan puute vaan **löydös**: valtaosa
lakialoitteista ei etene minnekään. Joten oikea kysymys on: *mitä niille sitten
tapahtuu — ja miksi niitä tehdään?*
```{r setup}
#| cache: false
library(tidyverse); library(here); library(qs2); library(ggdist); library(scales); library(patchwork)
select <- dplyr::select; filter <- dplyr::filter
set.seed(20270418)
pal <- c(punainen="#e63946", turkoosi="#2a9d8f", oranssi="#f4a261",
laivasto="#1d3557", sininen="#457b9d")
theme_set(theme_minimal(base_size = 13) +
theme(plot.title = element_text(face="bold"), plot.subtitle = element_text(color="grey30"),
panel.grid.minor = element_blank(), legend.position = "top"))
DATA <- here("data", "eduskunta")
init <- qs2::qd_read(file.path(DATA, "vaski_init.qs"))
tulokset <- qs2::qd_read(file.path(DATA, "aloite_tulokset.qs"))
mp <- qs2::qs_read(file.path(DATA, "mp.qs"))
mp_years <- qs2::qs_read(file.path(DATA, "mp_years.qs"))
ryhma_years <- qs2::qs_read(file.path(DATA, "ryhma_years.qs"))
#vaski_raw <- qs2::qd_read(file.path(DATA, "vaski_raw.qs")) #Tarvitaan vain omalla koneella la_status-tuotantoon.
vaski_docs <- qs2::qd_read(file.path(DATA, "vaski_docs.qs"))
```
## Kolme kohtaloa: oma mietintö, maininta, raukeaminen
Lakialoitteella on käytännössä kolme mahdollista jälkeä. Se voi (1) saada **oman
valiokuntamietinnön** (harvinaista), (2) tulla **mainituksi** jonkin mietinnön
käsittelyssä — tyypillisesti hallituksen esityksen rinnalla — tai (3) **raueta**
ilman jälkeä. Rakennamme nämä kolme luokkaa.
```{r kohtalot}
#| cache: false
norm_tunnus <- function(x) str_remove_all(str_to_upper(x), "\\s") |> str_remove("VP$")
status_path <- file.path(DATA, "la_status.qs")
if (!file.exists(status_path)) {
# Poimi kaikki LA-viittaukset valiokuntamietintöjen KOKO tekstistä
poimi_la <- function(xml_str) {
txt <- tryCatch(xml2::xml_text(xml2::read_xml(xml_str)), error = function(e) "")
unique(norm_tunnus(str_extract_all(txt, "(?i)LA\\s?\\d+/\\d{4}")[[1]]))
}
mietinnot <- vaski_docs |> filter(str_detect(tyyppi, "VM$")) |>
left_join(vaski_raw |> select(Id, XmlData), by = c("id" = "Id"))
mainitut <- mietinnot$XmlData |> map(poimi_la) |> unlist() |> unique()
qs2::qd_save(tibble(la_norm = mainitut), status_path)
}
mainitut <- qs2::qd_read(status_path)$la_norm
la <- init |> filter(tyyppi == "LA") |>
mutate(n_allek = map_int(allekirjoittajat, length),
tunnus_norm = norm_tunnus(tunnus)) |>
left_join(tulokset |> select(id, oma_mietinto = eteni), by = "id") |>
mutate(oma_mietinto = replace_na(as.logical(oma_mietinto), FALSE),
kohtalo = case_when(
oma_mietinto ~ "Sai oman mietinnön",
tunnus_norm %in% mainitut ~ "Mainittu mietinnössä",
TRUE ~ "Rauennut / ei käsitelty") |>
factor(levels = c("Sai oman mietinnön","Mainittu mietinnössä","Rauennut / ei käsitelty")))
stopifnot("LA-taulu tyhjä" = nrow(la) > 100)
jakauma <- la |> count(kohtalo) |> mutate(osuus = n/sum(n))
jakauma
```
## Jakauma ensin: valtaosa raukeaa
```{r jakauma-kuva}
ggplot(jakauma, aes(x = osuus, y = fct_rev(kohtalo), fill = kohtalo)) +
geom_col() +
geom_text(aes(label = percent(osuus, .1)), hjust = -0.1, size = 3.6) +
scale_x_continuous(labels = label_percent(), expand = expansion(c(0,.18))) +
scale_fill_manual(values = unname(pal[c(2,5,1)]), guide = "none") +
labs(title = "Lakialoitteen kolme kohtaloa",
subtitle = "Osuus kaikista lakialoitteista", x = NULL, y = NULL)
```
Tässä on koko postauksen kärki yhtenä kuvana. Jos joku sanoisi "lakialoitteiden
läpimenoprosentti on X", se olisi pistearvo, joka piilottaa olennaisen: **valtaosa
ei etene lainkaan**, ja "läpimeno" omana esityksenä on
`r scales::percent(jakauma$osuus[jakauma$kohtalo == "Sai oman mietinnön"], 0.1)`
luokkaa. Jakauma kertoo sen, minkä yksi luku kätkisi.
## Kuka lakialoitteita tekee?
Jos aloitteet eivät juuri etene, miksi niitä tehdään paljon? Katsotaan tekijöitä.
Rakennamme aseman (hallitus/oppositio) jättövuoden mukaan.
```{r asema}
hallitus <- tribble(
~vuosi, ~hallituspuolueet,
2015,c("Keskusta","Perussuomalaiset","Kokoomus"), 2016,c("Keskusta","Perussuomalaiset","Kokoomus"),
2017,c("Keskusta","Sininen","Kokoomus"), 2018,c("Keskusta","Sininen","Kokoomus"),
2019,c("Sosialidemokraattinen","Keskusta","Vihreä","Vasemmisto","Ruotsalainen"),
2020,c("Sosialidemokraattinen","Keskusta","Vihreä","Vasemmisto","Ruotsalainen"),
2021,c("Sosialidemokraattinen","Keskusta","Vihreä","Vasemmisto","Ruotsalainen"),
2022,c("Sosialidemokraattinen","Keskusta","Vihreä","Vasemmisto","Ruotsalainen"),
2023,c("Kokoomus","Perussuomalaiset","Ruotsalainen","Kristillisdemokraattinen"),
2024,c("Kokoomus","Perussuomalaiset","Ruotsalainen","Kristillisdemokraattinen"),
2025,c("Kokoomus","Perussuomalaiset","Ruotsalainen","Kristillisdemokraattinen"))
asema_taulu <- ryhma_years |> left_join(hallitus, by = "vuosi") |>
mutate(on_hallitus = map2_lgl(ryhma, hallituspuolueet,
\(r,h) if (is.null(h)) NA else any(str_detect(r, fixed(h, ignore_case = TRUE))))) |>
filter(!is.na(on_hallitus)) |>
group_by(tekija = henkilo_nro, vpvuosi = vuosi) |>
summarise(on_hallitus = mean(on_hallitus) >= 0.5, .groups = "drop") |>
transmute(tekija, vpvuosi, asema = if_else(on_hallitus, "Hallitus", "Oppositio"))
la_asema <- la |> left_join(asema_taulu, by = c("tekija","vpvuosi")) |> drop_na(asema)
# Volyymi ajassa aseman mukaan
vol <- la_asema |> count(vpvuosi, asema)
ggplot(vol, aes(vpvuosi, n, color = asema)) +
geom_line(linewidth = 1) + geom_point() +
scale_color_manual(values = unname(pal[c(4,1)])) +
labs(title = "Lakialoitteet ovat pääosin opposition väline",
subtitle = "Lakialoitteiden määrä jättäjän aseman mukaan",
x = NULL, y = "Lakialoitteita", color = NULL)
```
## Onko lakialoite opposition työkalu? Tilastollinen testi
Testataan suoraan: tekevätkö oppositioedustajat enemmän lakialoitteita kuin
hallitusedustajat? Rakennamme edustajavuositason aineiston (myös nollat mukana) ja
vertaamme jakaumia. Lukumäärädata on vino, joten käytämme jakaumavapaata
Wilcoxonin testiä ja efektikokona rank-biserialia.
```{r testi}
la_per_hlo <- la |> count(tekija, vpvuosi, name = "n_la")
paneeli <- mp_years |> distinct(henkilo_nro, vuosi) |>
filter(vuosi >= min(la$vpvuosi, na.rm = TRUE)) |>
left_join(asema_taulu, by = c("henkilo_nro" = "tekija", "vuosi" = "vpvuosi")) |>
left_join(la_per_hlo, by = c("henkilo_nro" = "tekija", "vuosi" = "vpvuosi")) |>
mutate(n_la = replace_na(n_la, 0L)) |> drop_na(asema)
wt <- wilcox.test(n_la ~ asema, data = paneeli)
n_opp <- sum(paneeli$asema == "Oppositio"); n_hal <- sum(paneeli$asema == "Hallitus")
rank_biserial <- 1 - 2 * unname(wt$statistic) / (n_opp * n_hal)
paneeli |> group_by(asema) |>
summarise(mediaani = median(n_la), keskiarvo = round(mean(n_la),2), n_edustajavuosia = n()) |>
bind_cols(tibble(p = signif(wt$p.value,3), rank_biserial = round(rank_biserial,3)))
```
::: {.callout-note title="Testin valinta"}
Vertaamme kahta ryhmää vinolla lukumäärämuuttujalla, jossa on paljon nollia, joten
keskiarvovertailu (t-testi) olisi harhaanjohtava. Wilcoxon vertaa koko jakaumia, ja
rank-biserial kertoo eron suuruuden. Nollat (edustajavuodet ilman yhtään aloitetta)
ovat mukana — muuten mittaisimme väärää populaatiota.
:::
## Keskittymä: harva tekee monta
```{r gini}
gini <- function(x){ x <- sort(x); n <- length(x); if (sum(x)==0) return(NA)
sum((2*seq_len(n)-n-1)*x)/(n*sum(x)) }
per_tekija <- la |> count(tekija, name = "n_la")
lorenz <- per_tekija |> arrange(n_la) |>
mutate(o_tekijat = row_number()/n(), o_aloitteet = cumsum(n_la)/sum(n_la))
ggplot(lorenz, aes(o_tekijat, o_aloitteet)) +
geom_abline(linetype = "dashed", color = "grey60") +
geom_area(fill = pal[["turkoosi"]], alpha = .3) +
geom_line(color = pal[["turkoosi"]], linewidth = 1) +
scale_x_continuous(labels = label_percent()) + scale_y_continuous(labels = label_percent()) +
labs(title = paste0("Lakialoitteiden teko on keskittynyttä (Gini ",
round(gini(per_tekija$n_la),2), ")"),
subtitle = "Lorenz-käyrä: harva edustaja tekee suuren osan aloitteista",
x = "Osuus tekijöistä", y = "Osuus lakialoitteista")
```
## Mitä tämä tarkoittaa — lakialoite signaalina
Kun yhdistää nämä: valtaosa lakialoitteista raukeaa, ne ovat pääosin opposition
tekemiä, ja niiden teko on keskittynyt harvoille. Tästä piirtyy tulkinta, joka on
sekä rehellinen että päättäjälle valaiseva: **lakialoite toimii useammin poliittisena
signaalina kuin väylänä lainsäädäntöön.** Se on tapa nostaa aihe esiin, osoittaa
kanta ja tuottaa julkinen dokumentti — ei realistinen reitti lakiin, koska
lainsäädäntö kulkee lähes aina hallituksen esitysten kautta.
::: {.callout-important title="Kuvaus, ei arvostelu"}
Tämä ei tarkoita, että lakialoitteet olisivat turhia tai tekijänsä epärehellisiä.
Signalointi on osa demokraattista prosessia: aihe voi myöhemmin päätyä hallituksen
esitykseksi, ja aloite on osa sitä keskustelua. Kuvaamme järjestelmän toimintaa,
emme arvota edustajien motiiveja.
:::
## Minne ennustaminen kuuluu
Jos haluaa ennustaa lainsäädännön läpimenoa, oikea kohde ei ole lakialoite vaan
**hallituksen esitys (HE)**: ne etenevät, niistä äänestetään, ja niissä on todellista
vaihtelua. Se on luonteva seuraava askel — ja siihen liittyy henkilötason
äänestysdata, jota käsittelemme myöhemmin.
## Uutiskoukku takaisin
Kannattaako lakialoitetta tehdä? Jos mittarina on laiksi tuleminen, vastaus on
lähes aina ei. Mutta se ei ole koko tarina — aloite on signaali, ja signaloinnilla
on oma arvonsa. Tärkeintä on, ettei "läpimenoprosentti" yhtenä lukuna piilota tätä
todellisuutta.
---
::: {.callout-tip title="Tehdäänkö teidän datallenne sama?"}
Kun oletettu mittari osoittautuu vääräksi, oikean kysymyksen löytäminen on puolet
työstä. Rakennan analytiikkaa, joka kertoo mitä data oikeasti tukee — ei mitä
haluttaisiin sen sanovan. **kristianvepsalainen.com**
:::
*Kiitos lukijalle kommenteista, jotka terävöittivät tätä osaa. Datalähde: Eduskunnan
avoin data, VaskiData (CC BY 4.0). Hallituskokoonpanot koodattu käsin.*