{"id":19863947,"url":"https://github.com/sandialabs/veesa","last_synced_at":"2026-04-21T13:04:38.059Z","repository":{"id":207620031,"uuid":"719701806","full_name":"sandialabs/veesa","owner":"sandialabs","description":"VEESA: Explainable machine learning with functional data","archived":false,"fork":false,"pushed_at":"2025-12-03T06:13:57.000Z","size":108614,"stargazers_count":1,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-12-06T06:51:36.540Z","etag":null,"topics":["scr-2946","snl-data-analysis"],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sandialabs.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-11-16T18:10:55.000Z","updated_at":"2025-12-03T06:14:00.000Z","dependencies_parsed_at":"2025-01-11T06:17:50.880Z","dependency_job_id":"c90bf2a2-67ee-493f-bf0f-cb70a0d4d57f","html_url":"https://github.com/sandialabs/veesa","commit_stats":null,"previous_names":["sandialabs/veesa"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/sandialabs/veesa","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandialabs%2Fveesa","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandialabs%2Fveesa/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandialabs%2Fveesa/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandialabs%2Fveesa/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sandialabs","download_url":"https://codeload.github.com/sandialabs/veesa/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandialabs%2Fveesa/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32093157,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-21T11:25:29.218Z","status":"ssl_error","status_checked_at":"2026-04-21T11:25:28.499Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["scr-2946","snl-data-analysis"],"created_at":"2024-11-12T15:16:48.100Z","updated_at":"2026-04-21T13:04:38.027Z","avatar_url":"https://github.com/sandialabs.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\ntitle: \"VEESA R Package\"\noutput: rmarkdown::github_document\nalways_allow_html: yes\n---\n\n\u003c!-- badges: start --\u003e\n[![CRAN status](https://www.r-pkg.org/badges/version/veesa)](https://CRAN.R-project.org/package=veesa)\n[![R-CMD-check](https://github.com/sandialabs/veesa/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/sandialabs/veesa/actions/workflows/R-CMD-check.yaml)\n[![Codecov test coverage](https://codecov.io/gh/sandialabs/veesa/graph/badge.svg)](https://app.codecov.io/gh/sandialabs/veesa)\n\u003c!-- badges: end --\u003e\n  \n```{r setup, include = FALSE}\n# Rmarkdown options\nknitr::opts_chunk$set(echo = TRUE, message = FALSE, dpi = 300)\n```\n\n`veesa` is an R package for implementing the VEESA pipeline for an explainable approach to training machine learning models with functional data inputs. See a preprint manuscript describing the approach on [arXiv](https://arxiv.org/abs/2501.07602). Installing `veesa` can be implemented using either of the commands below.\n\n```{r}\n#| eval: false\n\n# CRAN\ninstall.packages(\"veesa\")\n\n# Development version from GitHub\nremotes::install_github(\"sandialabs/veesa\")\n```\n\nKeep reading for an example using `veesa` to implement the VEESA pipeline.\n\n## Demonstration\n\n#### Set Up and Data Generation\n\n```{r}\n#| message: false\n# Load R packages\nlibrary(cowplot)\nlibrary(dplyr)\nlibrary(ggplot2)\nlibrary(purrr)\nlibrary(randomForest)\nlibrary(tidyr)\nlibrary(veesa)\n\n# Specify a color palette\ncolor_pal = wesanderson::wes_palette(\"Zissou1\", 5, type = \"continuous\")\n\n# Specify colors for PC direction plots\ncol_plus1 = \"#784D8C\"\ncol_plus2 = \"#A289AE\"\ncol_minus1 = \"#EA9B44\"\ncol_minus2 = \"#EBBC88\"\ncol_pcdir_1sd = c(col_plus1, \"black\", col_minus1)\ncol_pcdir_2sd = c(col_plus2, col_plus1, \"black\", col_minus1, col_minus2)\n```\n\nSimulate data:\n\n```{r}\nsim_data = simulate_functions(M = 100, N = 75, seed = 20211130)\n```\n\nSeparate data into training/testing:\n\n```{r}\nset.seed(20211130)\nid = unique(sim_data$id)\nM_test = length(id) * 0.25\nid_test = sample(x = id, size = M_test, replace = FALSE)\nsim_data = sim_data %\u003e% mutate(data = ifelse(id %in% id_test, \"test\", \"train\"))\n```\n\nSimulated functions colored by covariates: \n\n```{r echo = FALSE}\n#| fig-height: 5\n#| fig-width: 27\nplot_sim \u003c- function(cov) {\n  sim_data %\u003e%\n    ggplot(aes(x = t, y = y, color = get(cov), group = id)) + \n    geom_line(alpha = 0.75) + \n    scale_color_gradientn(colours =  color_pal) +\n    theme_bw(base_size = 20) + \n    labs(color = cov)\n}\nsim_plot = map(.x = c(\"x1\", \"x2\", \"x3\"), .f = plot_sim)\nplot_grid(plotlist = sim_plot, ncol = 3, byrow = FALSE)\n```\n\nPrepare matrices from the data frames:\n\n```{r}\nprep_matrix \u003c- function(df, train_test) {\n  df %\u003e%\n    filter(data == train_test) %\u003e%\n    select(id, t, y) %\u003e%\n    ungroup() %\u003e%\n    pivot_wider(id_cols = t,\n                names_from = id,\n                values_from = y) %\u003e%\n    select(-t) %\u003e%\n    as.matrix()\n}\nsim_train_matrix = prep_matrix(df = sim_data, train_test = \"train\")\nsim_test_matrix = prep_matrix(df = sim_data, train_test = \"test\")\n```\n\nCreate a vector of times:\n\n```{r}\ntimes = sim_data$t %\u003e% unique()\n```\n\n#### Alignment and fPCA\n\nPrepare train data\n\n```{r}\ntrain_transformed_jfpca \u003c-\n  prep_training_data(\n    f = sim_train_matrix,\n    time = times, \n    fpca_method = \"jfpca\",\n    optim_method = \"DPo\"\n  )\n```\n\nPrepare test data:\n\n```{r}\ntest_transformed_jfpca \u003c-\n  prep_testing_data(\n    f = sim_test_matrix,\n    time = times,\n    train_prep = train_transformed_jfpca,\n    optim_method = \"DPo\"\n  )\n```\n\nPlot several PCs:\n\n```{r}\n#| fig-height: 5\n#| fig-width: 20\n#| echo: false\nplot_pc_directions(\n  fpcs = 1:3,\n  fdasrvf = train_transformed_jfpca$fpca_res,\n  fpca_method = \"jfpca\",\n  time = times,\n  linesizes = rep(1, 5)\n) + \n  scale_color_manual(values = col_pcdir_2sd) + \n  theme_bw(base_size = 20) + \n  labs(\n    x = \"Time\",\n    y = \"Intensity\"\n  )\n```\n\nCompare jfPCA coefficients from train and test data:\n\n```{r}\n#| fig-height: 4\n#| fig-width: 10\n#| out-width: \"75%\"\n#| fig-align: \"center\"\n#| echo: false\n\ntrain_plot_df_jfpca \u003c- \n  train_transformed_jfpca$fpca_res$coef %\u003e%\n  t() %\u003e%\n  data.frame() %\u003e%\n  mutate(pc = 1:n()) %\u003e%\n  pivot_longer(cols = -pc, names_to = \"id\") %\u003e%\n  mutate(data = \"train\")\n\ntest_plot_df_jfpca \u003c- \n  test_transformed_jfpca$coef %\u003e%\n  data.frame() %\u003e%\n  mutate(pc = 1:n()) %\u003e%\n  pivot_longer(cols = -pc, names_to = \"id\") %\u003e%\n  mutate(data = \"test\")\n\nbind_rows(train_plot_df_jfpca, test_plot_df_jfpca) %\u003e%\n  ggplot(aes(\n    x = pc,\n    y = value,\n    group = factor(id):factor(data),\n    color = data\n  )) +\n  geom_line(alpha = 0.5) +\n  labs(\n    title = \"Joint fPCA\", \n    color = \"Data\",\n    x = \"PC number\",\n    y = \"Coefficient\") +\n  theme_bw()\n```\n\n#### Models\n\nCreate response variable: \n\n```{r}\nx1_train \u003c- \n  sim_data %\u003e% filter(data == \"train\") %\u003e%\n  select(id, x1) %\u003e%\n  distinct() %\u003e% \n  pull(x1)\n```\n\nCreate data frame with PCs and response for random forest:\n\n```{r}\nrf_jfpca_df \u003c- \n  train_transformed_jfpca$fpca_res$coef %\u003e%\n  data.frame() %\u003e%\n  rename_all(.funs = function(x) stringr::str_replace(x, \"X\", \"pc\")) %\u003e%\n  mutate(x1 = x1_train) %\u003e%\n  select(x1, everything())\n```\n\nFit random forest:\n\n```{r}\nset.seed(20211130)\nrf_jfpca = randomForest(x1 ~ ., data = rf_jfpca_df)\n```\n\n#### PFI\n\nCompute PFI:\n\n```{r}\nset.seed(20211130)\npfi_jfpca \u003c- compute_pfi(\n  x = rf_jfpca_df %\u003e% select(-x1),\n  y = rf_jfpca_df$x1,\n  f = rf_jfpca,\n  K = 10,\n  metric = \"nmse\"\n)\n```\n\nPFI results (mean of reps):\n\n```{r}\n#| fig-height: 4.5\n#| fig-width: 12\n#| out-width: \"75%\"\n#| fig-align: \"center\"\n#| echo: false\ndata.frame(pfi = pfi_jfpca$pfi) %\u003e%\n  mutate(pc = 1:n()) %\u003e%\n  ggplot(aes(x = pc, y = pfi)) +\n  geom_point() +\n  geom_segment(aes(yend = 0, xend = pc)) +\n  theme_bw(base_size = 14) +\n  labs(\n    x = \"Principal Component\",\n    y = \"Permutation Feature Importance\"\n  )\n```\n\nPFI results (variability across reps):\n\n```{r}\n#| fig-height: 4.5\n#| fig-width: 12 \n#| out-width: \"75%\"\n#| fig-align: \"center\"\n#| echo: false\npfi_jfpca$pfi_single_reps %\u003e%\n  data.frame() %\u003e%\n  mutate(rep = 1:n()) %\u003e%\n  pivot_longer(cols = -rep,\n               names_to = \"pc\",\n               values_to = \"pfi\") %\u003e%\n  mutate(pc = stringr::str_remove(pc, \"X\")) %\u003e%\n  mutate(pc = as.numeric(pc)) %\u003e%\n  ggplot(aes(x = pc, y = pfi, group = pc)) +\n  geom_boxplot() +\n  theme_bw(base_size = 14) +\n  labs(\n    x = \"Principal Component\",\n    y = \"Permutation Feature Importance\"\n  )\n```\n\nIdentify the top PC for each elastic fPCA method:\n\n```{r}\ntop_pc_jfpca \u003c- \n  data.frame(pfi = pfi_jfpca$pfi) %\u003e%\n  mutate(pc = 1:n()) %\u003e%\n  arrange(desc(pfi)) %\u003e%\n  slice(1) %\u003e%\n  pull(pc)\n```\n\nPrincipal directions of top PC for each jfPCA method:\n\n```{r}\n#| fig-height: 4\n#| fig-width: 8 \n#| out-width: \"60%\"\n#| fig-align: \"center\"\n#| echo: false\nplot_pc_directions(\n  fpcs = top_pc_jfpca,\n  fdasrvf = train_transformed_jfpca$fpca_res,\n  fpca_method = \"jfpca\",\n  nrow = 2, \n  linesizes = rep(1, 5)\n) +\n  scale_color_manual(values = col_pcdir_2sd) +\n  labs(title = \"Top PC for Joint fPCA\")\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandialabs%2Fveesa","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsandialabs%2Fveesa","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandialabs%2Fveesa/lists"}