Skip to contents

This tutorial walks through a complete multi-domain regional analysis — from raw Eurostat data to publication-ready maps and Tableau exports. We combine economy, labour, health, and education indicators into a unified subnational dashboard covering 235+ European NUTS 2 regions.

Phase 1: Data Acquisition

Understanding the Data Model

Eurostat organizes subnational statistics using the NUTS classification:

  • NUTS 0 — Country level (e.g., DE for Germany)
  • NUTS 1 — Major socio-economic regions (e.g., DE1 for Baden-Württemberg)
  • NUTS 2 — Basic regions (e.g., DE11 for Stuttgart)

Not all countries report at NUTS 2. localintel handles this through data cascading (Phase 3).

Browsing the Indicator Registry

n <- indicator_count()
cat(n$indicators, "indicators across", n$domains, "domains\n")
print(n$by_domain)

Fetching Multiple Domains

# Economy
econ_data <- fetch_eurostat_batch(economy_codes(), level = 2, years = 2010:2024)

# Labour market
lab_data <- fetch_eurostat_batch(labour_codes(), level = 2, years = 2010:2024)

# Health
hlth_data <- fetch_eurostat_batch(health_system_codes(), level = 2, years = 2010:2024)

# Education
educ_data <- fetch_eurostat_batch(education_codes(), level = 2, years = 2010:2024)

# Drop any empty results
econ_data <- drop_empty(econ_data)
lab_data  <- drop_empty(lab_data)
hlth_data <- drop_empty(hlth_data)
educ_data <- drop_empty(educ_data)

Phase 2: Data Processing

Domain-Specific Processors

Each domain has convenience processors that filter the right dimensions:

# Economy
gdp           <- process_gdp(econ_data$gdp_nuts2)

# Labour
unemp         <- process_unemployment_rate(lab_data$unemployment_rate)
empl_rate     <- process_eurostat(lab_data$employment_rate,
                   filters = list(sex = "T", age = "Y20-64"),
                   out_col = "employment_rate")

# Health
beds          <- process_beds(hlth_data$beds)
physicians    <- process_physicians(hlth_data$physicians)

# Education
tertiary      <- process_education_attainment(educ_data$attain_tertiary)

The Generic Processor

For datasets without a dedicated processor, use process_eurostat():

# Tourism: nights spent
nights_raw <- get_nuts_level_robust("tour_occ_nin2", level = 2, years = 2010:2024)
nights     <- process_eurostat(nights_raw,
  filters = list(unit = "NR", nace_r2 = "I551-I553", c_resid = "TOTAL"),
  out_col = "nights_spent")

# R&D expenditure
rd_raw <- get_nuts_level_robust("rd_e_gerdreg", level = 2, years = 2010:2024)
rd     <- process_eurostat(rd_raw,
  filters = list(unit = "PC_GDP", sectperf = "TOTAL"),
  out_col = "rd_expenditure")

Merging

Combine all indicators into one table:

all_data <- merge_datasets(gdp, unemp, empl_rate, beds, physicians, tertiary)
glimpse(all_data)

Phase 3: Data Cascading

Getting Reference Data

nuts2_ref <- get_nuts2_ref()
geopolys  <- get_nuts_geopolys()

Generic Cascade (Any Domain)

cascaded <- cascade_to_nuts2(
  all_data,
  vars = c("gdp", "unemployment_rate", "employment_rate",
           "beds", "physicians", "education_attainment"),
  nuts2_ref = nuts2_ref,
  years = 2010:2024
)

# Check coverage
cascaded %>%
  summarise(across(starts_with("src_"), ~sum(!is.na(.)))) %>%
  glimpse()

Health-Specific Cascade (with DA/rLOS)

For health indicators, the specialized cascade also computes derived indicators:

cascaded_health <- cascade_to_nuts2_and_compute(
  all_data,
  vars = c("disch_inp", "disch_day", "beds", "physicians", "los"),
  nuts2_ref = nuts2_ref,
  years = 2010:2024
)

Phase 4: Scoring

scored <- cascaded %>%
  keep_eu27() %>%
  transform_and_score(list(
    unemp_tr = "-unemployment_rate",
    gdp_tr   = "safe_log10(gdp)",
    beds_tr  = "beds",
    educ_tr  = "education_attainment"
  ))

Phase 5: Visualization

plot_best_by_country_level(
  cascaded, geopolys,
  var = "unemployment_rate",
  years = 2022:2024,
  title = "Unemployment Rate (%)",
  scale = "global"
)

plot_best_by_country_level(
  cascaded, geopolys,
  var = "gdp",
  years = 2022:2024,
  title = "GDP (million EUR)"
)

Phase 6: Multi-Domain Tableau Export

sf_all <- build_multi_var_sf(
  cascaded, geopolys,
  vars = c("gdp", "unemployment_rate", "beds", "education_attainment"),
  years = 2010:2024,
  var_labels = regional_var_labels(),
  pillar_mapping = regional_domain_mapping()
)

pop_data    <- get_population_nuts2()
nuts2_names <- get_nuts2_names()
sf_enriched <- enrich_for_tableau(sf_all, pop_data, nuts2_names)

export_to_geojson(sf_enriched, "output/multi_domain_dashboard.geojson")
export_to_excel(cascaded, "output/cascaded_multi_domain.xlsx")