EU:n lainsäädäntö jakaumana — Osa 1: Eksploratiivinen data-analyysi

Mitä eurlex-paketti paljastaa, kun kohtelet säädöskorpusta tilastollisena ilmiönä?

Tekijä

Kristian Vepsäläinen

Julkaistu

21.5.2026

Koodi
library(tidyverse)
library(lubridate)
library(scales)
library(patchwork)
library(ggtext)

col_red    <- "#e63946"
col_green  <- "#2a9d8f"
col_orange <- "#f4a261"
col_navy   <- "#1d3557"
col_blue   <- "#457b9d"

theme_set(
  theme_minimal(base_size = 14) +
    theme(
      plot.title    = element_markdown(face = "bold", size = 15),
      plot.subtitle = element_markdown(color = "grey40"),
      plot.caption  = element_text(color = "grey55", size = 9),
      axis.title    = element_text(color = "grey30"),
      panel.grid.minor = element_blank()
    )
)

Miksi EU-lainsäädäntö on kiinnostavaa datana?

Useimmat ihmiset kohtaavat EU:n lainsäädännön yksittäisinä säädöksinä — direktiiveinä, asetuksina, päätöksinä — joita kommentoidaan julkisessa keskustelussa pistearvoina: “direktiivi X astuu voimaan”, “asetus Y muuttaa käytäntöä Z”.

Tämä on vähän kuin yrittäisi ymmärtää suomalaista säätä katsomalla yksittäistä lämpötilamittausta.

Maailma on jakauma. Myös EU:n lainsäädäntö on jakauma — itse asiassa monta päällekkäistä jakaumaa:

  • Säädösten tuotantonopeus vaihtelee ajan myötä (poliittinen aktiivisuus, kriisit, laajentuminen)
  • Säädösten pituus ja kompleksisuus jakautuvat epätasaisesti säädöstyypin ja toimialan mukaan
  • Voimassaoloaika ennen kumoamista tai muuttamista on stokastinen prosessi, ei deterministinen
  • Direktiivien implementointiviive jäsenvaltioissa on jakauma, jolla on poliittinen ja juridinen merkitys

Tässä postauksessa teen eksploratiivisen data-analyysin (EDA) käyttäen R:n eurlex-pakettia, joka tarjoaa suoran pääsyn EUR-Lex:in SPARQL-rajapintaan. Tulokset ovat todellista dataa — ei simuloitua.


Datan haku: eurlex-paketti ja sen mahdollisuudet

eurlex hakee metadatan suoraan EUR-Lex:in Cellar-tietokannasta SPARQL-rajapinnan kautta. Perusyksikkö on CELEX-numero, EU:n säädösten yksilöivä tunniste — rakenne kertoo jo paljon: 32024R0903 = sektori 3 (lainsäädäntö), vuosi 2024, asetus (R), järjestysnumero 903.

Mitä kaikkea paketilla voi hakea?

Paketti tukee yhdeksää asiakirjatyyppiä, jotka avaavat EU:n toimintaan täysin erilaisia näkökulmia:

Tyyppi Kuvaus Analyyttinen potentiaali
regulation Asetukset Suoraan sovellettava lainsäädäntö, volyymianalyysi
directive Direktiivit Implementointiviiveet jäsenvaltioittain
decision Päätökset Komission päätöksenteon rakenne ja rytmi
recommendation Suositukset Pehmeän sääntelyn kasvu suhteessa kovaan
intagr Kansainväliset sopimukset EU:n ulkosuhdeaktiivisuus ajan myötä
caselaw Oikeustapaukset (EUT, EGT) Tuomioistuinten työmäärä, oikeuskäytännön kehitys
proposal Komission lainsäädäntöehdotukset Ehdotusten läpimenoaika ja “kuolleisuus”
national_impl Kansalliset implementointidokumentit Jäsenvaltioiden nopeus direktiivien toimeenpanossa
manual Muut asiakirjat (SWD, vaikutusarviot) Komission valmistelutyön volyymi

Erityisesti oikeustapausdata (caselaw) on analyyttisesti kiinnostava: tuomareiden nimet, asianosaisvaltiot, menettelytyypit ja viittaukset ovat kaikki saatavilla — täysi verkostoanalyysi EU-oikeuden kehityksestä on periaatteessa muutaman SPARQL-kyselyn päässä. Samoin ehdotusdata (proposal) yhdistettynä lopulta hyväksyttyihin säädöksiin mahdollistaa lainsäädäntöprosessin keston ja pullonkaulojen kvantifioinnin.

Mitä tässä analyysissa käytetään?

Tässä EDA-osassa rajaudutaan neljään sitovaan lainsäädäntötyyppiin, jotka muodostavat EU:n varsinaisen normiston. Rajaus on tietoinen: caselaw, proposal ja national_impl ansaitsevat kukin oman analyysinsä — ne käsitellään sarjan tulevissa osissa.

Käytännön syy erillisille hauille on tekninen: any-haku ilman rajausta osuu SPARQL-rajapinnan miljoonan rivin oletusrajaan ja tuottaa katkaistun otoksen. Hakemalla neljä tyyppiä erikseen voidaan varmistaa, että jokainen on kokonainen.

Tarkastelu rajataan vuoteen 2024, koska voidaan olettaa, että kyseinä vuonna annetut säädökset ovat ehtineet mennä koko prosessin läpi. Vuosien 2025 ja 2026 mukaan ottaaminen johtaisi siihen, että kaikki kuvaajat tekisivät voimakkaan piikin alaspäin, koska näiden osalta prosessit ovat vielä kesken. Näiden vuosien mukanaolo antaisi lukijalle väärän kuvan datasta.

Koodi
data_path <- here::here("data/eu/eu_saadanto_raw.rds")

if (!file.exists(data_path)) {
  tyypit <- c("regulation", "directive", "decision", "recommendation")
  
  hae_tyyppi <- function(tyyppi) {
    message("Haetaan: ", tyyppi)
    tulos <- elx_make_query(
      resource_type = tyyppi,
      include_date  = TRUE,
      include_force = TRUE,
      include_celex = TRUE
    ) |> elx_run_query()
    tulos |> mutate(resource_type = tyyppi)
  }
  
  raw <- map(tyypit, hae_tyyppi) |> bind_rows()
  dir.create(dirname(data_path), showWarnings = FALSE, recursive = TRUE)
  saveRDS(raw, data_path)
  message("Data haettu ja tallennettu: ", nrow(raw), " riviä")
  
} else {
  raw <- readRDS(data_path)
  message("Data ladattu tiedostosta: ", nrow(raw), " riviä")
}
#cat("\nYhteensä:", nrow(raw), "riviä neljästä asiakirjatyypistä\n")
Koodi
df <- raw |>
  filter(!is.na(celex), !is.na(date)) |>
  mutate(
    date        = as.Date(date),
    vuosi       = year(date),
    vuosikymmen = floor(vuosi / 10) * 10,
    saadostyyppi = case_when(
      resource_type == "regulation"     ~ "Asetus",
      resource_type == "directive"      ~ "Direktiivi",
      resource_type == "decision"       ~ "Päätös",
      resource_type == "recommendation" ~ "Suositus"
    ),
    voimassa = case_when(
      force == "true"  ~ "Voimassa",
      force == "false" ~ "Kumottu / vanhentunut",
      TRUE             ~ "Tuntematon"
    )
  ) |>
  filter(vuosi >= 1952, vuosi <= 2024)

cat("Analyysissa mukana:\n")
Analyysissa mukana:
Koodi
count(df, saadostyyppi, sort = TRUE) |>
  mutate(osuus = percent(n / sum(n), 0.1)) |>
  print()
  saadostyyppi      n osuus
1       Asetus 142861 70.6%
2       Päätös  51468 25.4%
3   Direktiivi   4361  2.2%
4     Suositus   3682  1.8%

EDA 1: Tuotantonopeus — kuinka paljon EU lainsäätää?

Ensimmäinen kysymys: onko EU:n lainsäädäntötehdas kiihtynyt vai hidastunut ajan mittaan? Pistemäinen vastaus (“EU säätää paljon”) on hyödytön. Jakauma kertoo enemmän.

Koodi
vuosi_df <- df |>
  filter(saadostyyppi %in% c("Asetus", "Direktiivi", "Päätös")) |>
  count(vuosi, saadostyyppi)

ggplot(vuosi_df, aes(vuosi, n, color = saadostyyppi)) +
  geom_line(linewidth = 0.8, alpha = 0.85) +
  geom_smooth(aes(group = saadostyyppi), method = "loess", span = 0.15,
              se = FALSE, linetype = "dashed", linewidth = 0.5, alpha = 0.5) +
  geom_vline(xintercept = c(1957, 1973, 1986, 1993, 2004, 2009),
             linetype = "dotted", color = "grey60", linewidth = 0.4) +
  annotate("text", x = c(1957, 1973, 1986, 1993, 2004, 2009),
           y = Inf, vjust = 1.3, hjust = -0.1, size = 2.8, color = "grey50",
           label = c("Rooman\nsopimus", "Laaj.\n(UK)", "Yhtenäis-\nakt", "Maastricht",
                     "Itä-Eu.\nlaaj.", "Lissabon")) +
  scale_color_manual(values = c(col_red, col_green, col_blue)) +
  scale_x_continuous(breaks = seq(1955, 2024, 10)) +
  scale_y_continuous(labels = comma_format(big.mark = " ")) +
  labs(
    title    = "EU:n **vuosittainen säädöstuotanto** ei ole stabiili prosessi",
    subtitle = "Asetusten piikki 1990-luvulla",
    x = NULL, y = "Säädösten lukumäärä", color = NULL,
    caption  = "Lähde: EUR-Lex SPARQL via eurlex (R). Kristian Vepsäläinen / kristianvepsalainen.com"
  ) +
  theme(legend.position = "top")

EU:n säädöstuotanto vuosittain 1952–2024. Pystyviivat merkitsevät keskeisiä institutionaalisia muutoksia.
Koodi
kumul <- df |>
  filter(saadostyyppi %in% c("Asetus", "Direktiivi", "Päätös")) |>
  count(vuosi, saadostyyppi) |>
  group_by(saadostyyppi) |>
  arrange(vuosi) |>
  mutate(kumulatiivinen = cumsum(n))

ggplot(kumul, aes(vuosi, kumulatiivinen, fill = saadostyyppi)) +
  geom_area(alpha = 0.75, position = "stack") +
  scale_fill_manual(values = c(col_red, col_green, col_blue)) +
  scale_y_continuous(labels = comma_format(big.mark = " ")) +
  scale_x_continuous(breaks = seq(1955, 2024, 10)) +
  labs(
    title    = "**Kumulatiivinen EU-säädöskanta** 1952–2024",
    subtitle = "Yli 200 000 säädöstä — mutta jakauma ajassa ei ole tasainen",
    x = NULL, y = "Kumulatiivinen lukumäärä", fill = NULL,
    caption  = "Lähde: EUR-Lex SPARQL via eurlex (R). Kristian Vepsäläinen / kristianvepsalainen.com"
  ) +
  theme(legend.position = "top")

Kumulatiivinen säädöskanta osoittaa lainsäädäntömassan kasvun.

EDA 2: Voimassaolo — eloonjäämisanalyysin perusteet

Kuinka kauan säädös pysyy voimassa ennen kumoamista tai muuttamista? Tämä on eloonjäämisanalyysin kysymys — ei pistemäinen vastaus vaan jakauma.

Koodi
eloo_df <- df |>
  filter(
    saadostyyppi %in% c("Asetus", "Direktiivi", "Päätös"),
    voimassa %in% c("Voimassa", "Kumottu / vanhentunut"),
    vuosi >= 1970
  ) |>
  mutate(
    ika_vuotta = if_else(
      voimassa == "Voimassa",
      as.numeric(Sys.Date() - date) / 365.25,
      NA_real_
    ),
    kohorttiryhmä = case_when(
      vuosi < 1980 ~ "1970-luku",
      vuosi < 1990 ~ "1980-luku",
      vuosi < 2000 ~ "1990-luku",
      vuosi < 2010 ~ "2000-luku",
      TRUE         ~ "2010-luku+"
    )
  )
Koodi
eloo_df |>
  filter(!is.na(ika_vuotta), ika_vuotta > 0) |>
  ggplot(aes(ika_vuotta, fill = kohorttiryhmä, color = kohorttiryhmä)) +
  geom_density(alpha = 0.35, linewidth = 0.7) +
  scale_fill_manual(values  = c(col_navy, col_blue, col_green, col_orange, col_red)) +
  scale_color_manual(values = c(col_navy, col_blue, col_green, col_orange, col_red)) +
  scale_x_continuous(limits = c(0, 55), breaks = seq(0, 55, 10)) +
  labs(
    title    = "**Voimassaolevien säädösten ikäjakauma** kohorteittain",
    subtitle = "Selviytymisharha: vanhoja säädöksiä on jäljellä vain kaikkein sitkeimmät",
    x = "Ikä vuosina (tähän päivään)", y = "Tiheys",
    fill = NULL, color = NULL,
    caption  = "Lähde: EUR-Lex SPARQL via eurlex (R). Kristian Vepsäläinen / kristianvepsalainen.com"
  ) +
  theme(legend.position = "top")

Voimassaolevien säädösten ikäjakauma kohorteittain. Vanhemmat kohortit ovat selektiivisiä — vain kaikkein ‘sitkeimmät’ säädökset ovat jääneet eloon.
Huomautus

Selviytymisharha (survival bias): Vanhoista kohorteista näemme vain ne säädökset, jotka ovat yhä voimassa. Kumottujen säädösten puuttuminen vääristää ikäjakaumaa. Seuraavassa osassa korjataan tämä Kaplan-Meier-estimaatilla, joka ottaa poistumisen huomioon.


EDA 3: Säädöstyyppijakauma — EU ei vain “direktiivi”

Julkisessa keskustelussa puhutaan usein vain direktiiveistä, vaikka asetusten lukumäärä on moninkertainen — ja päätöksiä on vielä enemmän kuin asetuksia.

Koodi
df |>
  count(saadostyyppi) |>
  mutate(
    osuus        = n / sum(n),
    saadostyyppi = fct_reorder(saadostyyppi, n)
  ) |>
  ggplot(aes(n, saadostyyppi, fill = saadostyyppi)) +
  geom_col(show.legend = FALSE, width = 0.7) +
  geom_text(
    aes(label = paste0(comma(n, big.mark = " "), "  (", percent(osuus, 0.1), ")")),
    hjust = -0.05, size = 3.5
  ) +
  scale_fill_manual(values = c(col_red, col_orange, col_green, col_blue)) +
  scale_x_continuous(expand = expansion(mult = c(0, 0.2)),
                     labels = comma_format(big.mark = " ")) +
  labs(
    title    = "**Direktiivi on harvinaisempi kuin luullaan**",
    subtitle = "Päätösten ja asetusten dominanssi on rakenteellinen piirre EU-oikeudessa",
    x = "Lukumäärä", y = NULL,
    caption  = "Lähde: EUR-Lex SPARQL via eurlex (R). Kristian Vepsäläinen / kristianvepsalainen.com"
  )

Säädöstyyppien lukumäärät ja osuudet koko korpuksessa.
Koodi
df |>
  filter(saadostyyppi %in% c("Asetus", "Direktiivi"), vuosi >= 1960) |>
  count(vuosi, saadostyyppi) |>
  pivot_wider(names_from = saadostyyppi, values_from = n, values_fill = 0) |>
  mutate(suhde = Asetus / (Direktiivi + 1)) |>
  ggplot(aes(vuosi, suhde)) +
  geom_line(color = col_navy, linewidth = 0.9) +
  geom_smooth(method = "loess", span = 0.2, se = TRUE,
              color = col_red, fill = col_red, alpha = 0.15) +
  geom_hline(yintercept = 1, linetype = "dashed", color = "grey60") +
  annotate("text", x = 1963, y = 1.15, label = "Yhtä monta",
           color = "grey50", size = 3.2) +
  scale_x_continuous(breaks = seq(1960, 2024, 10)) +
  labs(
    title    = "**Asetusten suhde direktiiveihin** 1960–2024",
    subtitle = "Asetusten ylivalta on kasvanut",
    x = NULL, y = "Asetusten lkm / direktiivien lkm",
    caption  = "Lähde: EUR-Lex SPARQL via eurlex (R). Kristian Vepsäläinen / kristianvepsalainen.com"
  )

Asetusten suhde direktiiveihin ajan myötä — sääntelytyyli on muuttunut.

EDA 4: Vuosikymmenten väliset jakaumat — pistearvot piilottavat kaiken

Koodi
df |>
  filter(
    saadostyyppi %in% c("Asetus", "Direktiivi", "Päätös", "Suositus"),
    vuosikymmen >= 1960,
    vuosikymmen <= 2020
  ) |>
  count(vuosikymmen, saadostyyppi) |>
  mutate(vuosikymmen = factor(paste0(vuosikymmen, "-luku"))) |>
  ggplot(aes(vuosikymmen, n, fill = saadostyyppi)) +
  geom_col(position = "dodge", width = 0.75) +
  scale_fill_manual(values = c(col_red, col_green, col_blue, col_orange)) +
  scale_y_continuous(labels = comma_format(big.mark = " ")) +
  labs(
    title    = "**EU:n säädöstuotanto vuosikymmenittäin**",
    subtitle = "1990-luku oli korkeavesimerkki — mutta ei kaikille tyypeille",
    x = NULL, y = "Säädösten lukumäärä", fill = NULL,
    caption  = "Lähde: EUR-Lex SPARQL via eurlex (R). Kristian Vepsäläinen / kristianvepsalainen.com"
  ) +
  theme(legend.position = "top",
        axis.text.x = element_text(angle = 20, hjust = 1))

Säädöstuotanto vuosikymmenittäin ja säädöstyypeittäin.

Yhteenveto: Mitä EDA paljasti?

Tämä oli vasta pintaraapaisu — datan perustopografia. Löydökset tiivistettynä:

Havainto Mitä se tarkoittaa
Päätökset ovat lukumäärältään suurin ryhmä Komissio toimii enemmän päätöksillä kuin julkinen keskustelu antaa ymmärtää
Asetusten dominanssi direktiiveihin nähden on kasvanut EU on siirtynyt kohti suoraan sovellettavaa oikeutta
1990-luku oli tuotannon huippu Itä-laajentumisen valmistelu + sisämarkkinoiden rakentaminen
Voimassaolevien säädösten ikäjakauma on selektiivinen Selviytymisharha — eloonjäämisanalyysi tarvitaan

Yksikään näistä ei olisi selvinnyt katsomalla yhtä pistettä. Kaikki paljastui katsomalla jakaumia.


Mitä seuraavaksi?

Osa 2 — Direktiivien implementointiviive jäsenvaltioissa Yhdistämällä EUR-Lex + jäsenvaltiokohtainen implementointidata: mikä maa on johdonmukaisesti myöhässä? Jakauman muoto itsessään on poliittinen signaali.

Osa 3 — Bayesilainen muutospiste-analyysi säädöstuotannolle Milloin EU:n lainsäädäntötahti muuttui rakenteellisesti? MCMC-malli kvantifioi epävarmuuden muutosajankohdassa — ei pelkkää silmämääräistä arvausta trendistä.

Osa 4 — Eloonjäämisanalyysi: Kuinka kauan EU-säädös elää? Kaplan-Meier + Cox-regressio: mitkä tekijät ennustavat säädöksen pitkää elinikää? Säädöstyyppi, poliittinen toimiala, alkuperäinen pituus?

Osa 5 — Säädösten viittausverkosto Mitkä säädökset ovat EU-oikeuden “solmupisteitä”? Verkostoanalyysi paljastaa juridiset riippuvuudet, joita ei voi nähdä yksittäistä säädöstä lukemalla.


Kaikki analyysi on toistettavissa. Koodi on avoin.

Tarvitsetko vastaavan analyysin omasta toimialastasi? Olen erikoistunut avoimeen dataan perustuvaan liiketoimintatiedusteluun — kristianvepsalainen.com