--- title: "Environmental Performance Index Case Study" output: rmarkdown::html_vignette bibliography: references.bib vignette: > %\VignetteIndexEntry{Environmental Performance Index Case Study} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") ``` ## Role of the case study The completed thesis analysed the 2024 Environmental Performance Index corpus for 180 countries. After missingness screening, low-variance filtering, and imputation, 70 predictor indicators were retained alongside the EPI response. The `.old` columns formed the training data and the aligned `.new` columns formed the test data. The package includes the supplied processed predictor and response matrices. The paired predictor matrices contain the same 70 named indicators and no missing values. Selected supplied output tables are retained separately as provenance fixtures. ## Bundled processed inputs ```{r} read_epi_file <- function(name) { utils::read.csv( system.file("extdata", "epi", name, package = "risdr"), check.names = FALSE ) } X_train <- read_epi_file("X_old.csv") X_test <- read_epi_file("X_new.csv") y_train <- read_epi_file("y_old.csv")[[1L]] y_test <- read_epi_file("y_new.csv")[[1L]] stopifnot( nrow(X_train) == 180L, nrow(X_test) == 180L, ncol(X_train) == 70L, identical(names(X_train), names(X_test)), length(y_train) == nrow(X_train), length(y_test) == nrow(X_test) ) ``` ## Original import and alignment protocol The transformation from the original EPI corpus should follow the structure below. It is not evaluated because the single source corpus is separate from the processed analysis matrices. ```{r raw-data-protocol, eval=FALSE} library(dplyr) library(readr) epi_data <- read_csv("data-raw/epi2024results.csv", show_col_types = FALSE) epi_old <- epi_data |> select(iso, country, ends_with(".old")) |> rename_with(\(x) sub("[.]old$", "", x)) epi_new <- epi_data |> select(iso, country, ends_with(".new")) |> rename_with(\(x) sub("[.]new$", "", x)) X_old_full <- epi_old |> select(-iso, -country) X_new_full <- epi_new |> select(-iso, -country) stopifnot(identical(names(X_old_full), names(X_new_full))) missing_prop_old <- colMeans(is.na(X_old_full)) keep_names <- names(missing_prop_old[missing_prop_old < 0.40]) X_old_reduced <- X_old_full[, keep_names, drop = FALSE] X_new_reduced <- X_new_full[, keep_names, drop = FALSE] training_variance <- vapply(X_old_reduced, var, numeric(1), na.rm = TRUE) keep_names <- names(training_variance[training_variance > 1e-6]) X_old_reduced <- X_old_reduced[, keep_names, drop = FALSE] X_new_reduced <- X_new_reduced[, keep_names, drop = FALSE] X_old_imputed <- VIM::kNN(X_old_reduced, k = 5, imp_var = FALSE) X_new_imputed <- VIM::kNN(X_new_reduced, k = 5, imp_var = FALSE) y_train <- X_old_imputed$EPI X_train <- X_old_imputed |> select(-EPI) y_test <- X_new_imputed$EPI X_test <- X_new_imputed |> select(-EPI) ``` Filtering and imputation choices must be estimated from the training data and then applied to the test data. Re-estimating preprocessing independently on the test data would weaken the interpretation of external prediction. ## Fitting template ```{r fitting-template, eval=FALSE} fit_epi <- fit_risdr( X = X_train, y = y_train, sdr_method = "phd", cov_method = "oas", nslices = 6, d_max = 10, selector = "cicomp", standardize = TRUE, stabilize = TRUE ) epi_prediction <- predict(fit_epi, X_test) evaluate_prediction(y_test, epi_prediction, d = fit_epi$d) ``` The thesis primary predictive comparison reports pHd as its best method, with approximately RMSE 2.905, MAE 2.321, `R^2` 0.935, adjusted `R^2` 0.933, and correlation 0.967. These values belong to that designated primary comparison. ## Broader method-covariance audit The package fixture below records a separate comparison across four SDR methods and five covariance estimators. It should not be conflated with the primary thesis comparison because the model grid and selected dimensions differ. ```{r} comparison_path <- system.file( "extdata", "epi", "epi_sdr_covariance_comparison_tidy.csv", package = "risdr" ) comparison <- utils::read.csv(comparison_path) comparison[ order(comparison$RMSE), c( "sdr_method", "cov_method", "selected_d", "condition_number", "RMSE", "MAE", "R2", "Adjusted_R2", "Correlation" ) ] ``` This audit demonstrates why predictive performance, structural dimension, and covariance conditioning must be reported together. A method may predict well under one estimator while retaining a different number of directions under another. ## Repeated cross-validation ```{r} cv_path <- system.file( "extdata", "epi", "epi_repeated_cv_summary_tidy.csv", package = "risdr" ) cv_summary <- utils::read.csv(cv_path) cv_summary[ order(cv_summary$mean_RMSE), c( "sdr_method", "cov_method", "n_success", "mean_selected_d", "mean_RMSE", "sd_RMSE", "mean_Adjusted_R2", "mean_Correlation" ) ] ``` The repeated assessment identifies SIR with ridge and SIR with OAS as highly competitive combinations. This complements, rather than replaces, the fixed old-to-new comparison. ## Interpretation discipline The EPI case study supports three distinct conclusions: 1. Prediction, subspace recovery, and structural dimension recovery are different objectives. 2. Covariance regularisation can materially improve numerical conditioning. 3. A single overall winner should not be declared without naming the objective, validation design, and covariance estimator. ## References