Skip to content

Latest commit

 

History

42 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

icare icare logo

Intelligent ClinlAbomics Research Expedition

A modular R framework that takes clinical / omics data all the way from raw table to publication-ready figures: statistics and missing-data handling, feature selection, machine-learning benchmarking, unsupervised subtyping (K-means, NMF, latent profile analysis), and prognostic / survival modeling — each with an interactive Shiny deployment layer.

License: GPL-3 R Status

Maintainer: Huaichao Luo (luohc@uestc.edu.cn) — Google Scholar | ResearchGate | Lab Twitter/X

Contributor: Guangchuang Yu — Lab website (yulab-smu.top)


Contents


Overview

icare organizes an analysis as a pipeline of S4 objects, one per stage, each produced by converting the previous one with ConvertObject():

raw data.frame
      │  CreateStatObject()
      ▼
  Stat object  ──────────────► baseline table, group comparisons, DEG
      │  ConvertObject(to = "Train_Model")   ConvertObject(to = "Subtyping")   Stat_to_PrognosiX()
      ▼                                    ▼                                ▼
Train_Model object                 Subtyping object                PrognosiX object
(classification /                  (K-means / NMF / LPA)            (Cox / RSF / mlr3proba
 regression, caret)                                                  survival learners)
      │                                    │                                │
      ▼                                    ▼                                ▼
 ModelDeployment()                 New_Sub_Manager()               New_Prog_Manager()
      │                                    │                                │
      ▼                                    ▼                                ▼
deploy_clinlab_app()             launch_sub_deploy_app()          launch_prog_deploy_app()

Every stage keeps a record of what was done to the data (imputation values, scaling parameters, selected features, trained models) inside the object itself, so the exact same transformation can be replayed on new patients at prediction time.

Installation

# install.packages("remotes")
remotes::install_github("<your-org>/icare")

icare depends on a large number of Bioconductor/CRAN packages (caret, mlr3 + mlr3proba/mlr3tuning, survival, NMF, mclust, DALEX, ComplexHeatmap, shiny, …) — see DESCRIPTION for the full list. A plain remotes::install_github() will pull in the required CRAN dependencies; Bioconductor packages (e.g. ComplexHeatmap) may need to be installed separately first with BiocManager::install().

The four modules

# Module S4 object What it does
1 Data cleaning Stat Type detection, missing-value imputation, outlier handling, one-hot encoding, normalization, differential-feature testing, baseline ("Table 1") reports
2 Modeling Train_Model Feature selection (RFE/GA/SA/built-in importance), train/test split, multi-algorithm benchmarking via caret, ensembling, hyperparameter tuning, SHAP/DALEX explainability, clinical thresholds & NRI/IDI
3 Subtyping Subtyping Unsupervised clustering (K-means, NMF, latent profile analysis), cluster validation & cross-method agreement, marker-feature discovery, t-SNE/UMAP visualization
4 Survival / Prognosis PrognosiX Cox / random-survival-forest / other mlr3proba learners, univariate + LASSO feature selection, risk stratification & KM curves, nomograms, decision-curve analysis

Each module ships with a QUICKSTART vignette (minimal, sensible defaults) and an ADVANCED vignette (every option, publication-style figures) under vignettes/ — start there for runnable, end-to-end examples on real data.


Essential Commands

The tables below are a fast reference for the functions you'll use most often in each module, grouped the way you'd actually call them in a script. They mirror the shape of a normal icare analysis — see the Quick start section for a compact end-to-end example, and the vignettes for fully worked ones.

Module 1 — Data cleaning (Stat)

# Build the container ---------------------------------------------------
stat_obj <- CreateStatObject(raw.data = mat, info.data = inf,
                              group_col = "group", na.action = "allow")

# Clean it, one step per line -------------------------------------------
stat_obj <- stat_diagnose_variable_type(stat_obj)      # detect numeric vs. categorical
stat_obj <- stat_convert_variables(stat_obj)           # apply those types
stat_obj <- stat_miss_processed(stat_obj, impute_method = "median_mode")  # impute
stat_obj <- stat_detect_and_mark_outliers(stat_obj, method = "iqr")      # flag outliers
stat_obj <- stat_handle_outliers(stat_obj, method = "impute")            # fix them
stat_obj <- stat_onehot_encode(stat_obj)               # encode categoricals
stat_obj <- stat_normalize_process(stat_obj, method = "auto")            # normalize

# Explore & compare groups -----------------------------------------------
PlotGroupedDistribution(stat_obj, features = numeric_vars, group_col = "group")
PlotPCA(stat_obj, color_by = "group", ellipse = TRUE)
stat_obj    <- stat_var_feature(stat_obj, p_threshold = 0.05)   # differential features
deg_result  <- ExtractLastTestSig(stat_obj)
stat_obj    <- stat_gaze_analysis(stat_obj, save_word = TRUE)   # baseline "Table 1"

# Hand off to Module 2 / 3 ------------------------------------------------
saveRDS(stat_obj, "stat_obj.rds")
Command Purpose
CreateStatObject() Wrap a raw data matrix + metadata into a Stat object
InspectObject() Print a structured summary of any icare S4 object
stat_diagnose_variable_type() / stat_convert_variables() Detect and coerce numeric vs. categorical columns
stat_miss_processed() Impute missing values ("median_mode", "mice", "knn", …)
stat_detect_and_mark_outliers() / stat_handle_outliers() Flag and remediate outliers (IQR, Z-score, …)
stat_onehot_encode() One-hot encode categorical variables
stat_normalize_process() Normalize numeric variables ("auto", "z_score", "min_max", …)
stat_var_feature() / batch_Wilcoxon() / ExtractLastTestSig() Univariate group-difference testing (differential features)
stat_gaze_analysis() Publication-style baseline characteristics table
PlotGroupedDistribution(), PlotPCA() Quick group-comparison and ordination plots

Module 2 — Modeling (Train_Model)

# Convert & select features -----------------------------------------------
model_obj <- ConvertObject(stat_obj, to = "Train_Model")
builtin   <- FeatureSelectBuiltin(model_obj, models = c("rf", "glm"), top_n = 15)
model_obj <- ApplyFeatureSelection(model_obj, builtin$importance_table$Feature)

# Split + scale (fit on train, apply to test — no leakage) ----------------
idx <- caret::createDataPartition(model_obj@clean.df[[model_obj@group_col]], p = 0.7, list = FALSE)
model_obj@split.data <- list(training = model_obj@clean.df[idx, ],
                              testing  = model_obj@clean.df[-idx, ])
preProc <- caret::preProcess(model_obj@split.data$training, method = c("center", "scale"))
model_obj@split.scale.data <- list(training = predict(preProc, model_obj@split.data$training),
                                    testing  = predict(preProc, model_obj@split.data$testing))
model_obj@filtered.set <- model_obj@split.scale.data

# Train, compare, ensemble, tune -------------------------------------------
model_obj <- ModelTrainAnalysis(model_obj, methods = c("glmnet", "rf", "gbm"))
model_obj <- SelectBestModel(model_obj, metric = "auc")
model_obj <- TrainEnsemble(model_obj, strategy = "stacking", top_n = 4)
model_obj <- FineTuneModel(model_obj, method = "rf", bounds = BuildTuningBounds(mtry = c(2, 15)))

# Explain & apply clinically -----------------------------------------------
explainer <- CreateExplainer(model_obj)
ExplainSHAPBeeswarm(explainer)
thresh <- CalculateThresholds(model_obj, target_ppv = 0.9)

# Deploy ---------------------------------------------------------------------
deploy_manager <- ModelDeployment(model_obj, preproc = preProc,
                                   class_labels = c("Negative", "Positive"))
deploy_clinlab_app(deploy_manager)
Command Purpose
ConvertObject(x, to = "Train_Model") Turn a cleaned Stat object into a modeling object
FeatureSelectBuiltin() / FeatureSelectionPipeline() (ga/rfe/sa) / run_feature_elimination() Feature selection: built-in importance, GA/RFE/SA, or performance-elbow elimination
ApplyFeatureSelection() Commit to a final feature set
PreprocessingBenchmark() / LogisticDiagnosticBenchmark() Compare imputation × normalization × algorithm combinations by CV performance
ModelTrainAnalysis() Train and cross-validate multiple caret algorithms at once
SelectBestModel() Pick the top-performing trained model
TrainEnsemble() Combine models: "stacking", "average", "weighted", "voting"
FineTuneModel() + BuildTuningBounds() / InspectHyperParams() Bayesian hyperparameter search around a chosen algorithm
CreateExplainer() + ExplainSHAP*() / ExplainVariableImportance() / ExplainPartialDependence() DALEX/SHAP-based model explainability
CalculateThresholds() / ApplyThreshold() / ClinicalThreshold() PPV/NPV/Youden decision thresholds
ClinicalCorrelation() / PlotSubgroupForest() / PlotConfounderForest() Clinical covariate correlation, subgroup and confounder-adjusted forest plots
CalculateCategoryNRI() / PlotIDICurve() / NRI_IDI_Analysis() Reclassification analysis (NRI/IDI) between two models
PlotMultiROC(), PlotConfusionMatrix(), PlotCalibration(), PlotFeatureImportance() Standard performance visualizations
ModelDeployment() + deploy_clinlab_app() Wrap trained model(s) + preprocessing into a predict function and Shiny app

Module 3 — Subtyping (Subtyping)

# Convert & normalize (min-max keeps values non-negative, required by NMF) --
sub_obj <- ConvertObject(stat_obj, to = "Subtyping")
sub_obj <- Sub_normalize_process(sub_obj, normalize_method = "min_max", group_col = "group")
sub_obj@scale.data <- remove_constant_columns(sub_obj@scale.data)

# Cluster: NMF (primary; produces a re-usable model) -------------------------
sub_obj <- Sub_nmf_estimate(sub_obj, rank_range = 2:6, nrun = 5, method = "brunet")
sub_obj <- Sub_nmf_best_rank(sub_obj, nrun = 5, method = "brunet")
sub_obj <- Sub_nmf_assign_subtypes(sub_obj)

# ... or K-means / LPA, and cross-compare -------------------------------------
sub_obj <- Sub_kmeans_with_optimal_k(sub_obj, k.max = 8)
sub_obj <- Sub_lpa_with_optimal_k(sub_obj, max_clusters = 3)
compare_clusterings(sub_obj, methods = c("cluster_kmeans", "cluster_lpa", "cluster_nmf"))

# Visualize, validate, find markers --------------------------------------------
sub_obj <- Sub_tsne_analyse(sub_obj, use_scaled_data = TRUE)
PlotDimReduction(sub_obj, reduction = "tsne", color_by = "cluster_nmf")
eval_result <- Sub_evaluation_results(sub_obj)
multi_deg   <- batch_Wilcoxon_MultiClass(mat = deg_df, group_col = "subtype")
PlotClusterHeatmap(sub_obj, deg_df = multi_deg, group_by = "cluster_nmf", top_n = 5)

# Deploy ------------------------------------------------------------------------
sub_manager <- New_Sub_Manager(sub_obj)
launch_sub_deploy_app(sub_manager)
Command Purpose
ConvertObject(x, to = "Subtyping") Turn a cleaned Stat object into a subtyping object
Sub_normalize_process() / Sub_extract_norm_params() / Sub_apply_norm_params() Fit normalization on training data and replay it on validation/new data
SplitSubtypingObject() Stratified train/validation split for cluster validation
Sub_kmeans_with_optimal_k() K-means with automatic k selection
Sub_lpa_with_optimal_k() Latent profile analysis (Gaussian mixture)
Sub_nmf_estimate()Sub_nmf_best_rank()Sub_nmf_assign_subtypes()Sub_nmf_train_model() Non-negative matrix factorization pipeline, including a re-usable model
Sub_predict_subtypes() Assign new/validation samples to existing subtypes
Sub_tsne_analyse() / Sub_umap_analyse() + PlotDimReduction() Dimensionality reduction for visualization
Sub_evaluation_results() Cluster-quality metrics (silhouette, etc.)
compare_clusterings() / plot_clustering_comparison() Adjusted Rand Index agreement between methods
batch_Wilcoxon_MultiClass() + PlotClusterHeatmap() / PlotGroupMeanHeatmap() Subtype-specific marker discovery and heatmaps
PlotSilhouette() / PlotMultiAlluvial() Separation diagnostics and multi-method/outcome alluvial plots
New_Sub_Manager() + launch_sub_deploy_app() Deploy the trained subtyping model as a Shiny app

Module 4 — Survival / Prognosis (PrognosiX)

# Convert (moves time/status into info.data, keeps numeric features) --------
stat <- CreateStatObject(raw.data = df, group_col = NULL, na.action = "allow")
prog <- Stat_to_PrognosiX(stat, time_col = "time", status_col = "status", min_events = 10)

# Feature selection: univariate Cox + LASSO -----------------------------------
feat_sel <- surv_feature_selection_multi(prog, methods = c("uni_cox", "lasso"), combine = "union")
prog@survival.var <- list(selected = feat_sel$selected)

# Train/validation split (mlr3 tasks) ------------------------------------------
task <- surv_extract_task(prog)$select(feat_sel$selected)
train_task <- task$clone()$filter(train_idx)
val_task   <- task$clone()$filter(val_idx)

# Benchmark algorithms, then train and tune the winner --------------------------
bmr   <- surv_run_algorithm_benchmark(train_task, learners_list = c("surv.coxph", "surv.ranger"))
learner <- surv_get_learner("surv.ranger", train_task)
learner$train(train_task)
tuned   <- surv_train_and_tune(train_task, "surv.ranger")

# Evaluate, stratify risk, and validate -----------------------------------------
surv_evaluate_model(learner, val_task)
km <- surv_plot_risk_km(learner, train_task, cutoff_method = "median", risk_table = TRUE)
nom <- surv_generate_nomogram(prog, features = feat_sel$selected)   # includes a PH check

# Predict for new patients and deploy ---------------------------------------------
predict_prognosix(prog, new_patients)
predict_risk_groups(prog, new_patients, cutoff_method = "median")
prog_manager <- New_Prog_Manager(prog)
launch_prog_deploy_app(prog_manager)
Command Purpose
Stat_to_PrognosiX() Convert a Stat object into a survival-modeling (PrognosiX) object
surv_feature_selection_multi() Univariate Cox / LASSO feature selection (combine = "union"/"intersect")
surv_extract_task() Build an mlr3proba::TaskSurv from a PrognosiX object
surv_get_learner() / surv_run_algorithm_benchmark() Instantiate or cross-validate mlr3proba survival learners (Cox, RSF, surv.ranger, …)
surv_train_and_tune() Hyperparameter tuning of a survival learner
surv_evaluate_model() C-index / Brier score / time-dependent AUC evaluation
surv_plot_risk_km() Kaplan–Meier risk stratification ("median", "tertile", "quartile", "p_optimize", "custom")
surv_generate_nomogram() Cox-based nomogram, with an automatic proportional-hazards (cox.zph) check
predict_prognosix() / predict_risk_groups() Score and risk-classify new patients
run_prognosis_pipeline() End-to-end orchestration of the steps above in one call
New_Prog_Manager() + launch_prog_deploy_app() Deploy the trained survival model as a Shiny app

Methodological note. Several of the "essential commands" above only report an unbiased estimate of performance when you actually pass a held-out split (val_task, split.data$testing, …) rather than re-using the data a model was trained/tuned on — e.g. surv_plot_risk_km() and surv_generate_nomogram() will happily run on the training task, but the resulting p-values/HRs should then be treated as descriptive, not confirmatory. See each function's documentation for details.


Quick start

The fastest way to see the whole pipeline end-to-end is the QUICKSTART vignette for each module, in order:

library(icare)

# Module 1: raw data -> cleaned Stat object -> stat_obj.rds
source(system.file("vignettes", "01_module1_data_cleaning_QUICKSTART.R", package = "icare"))

# Module 2: stat_obj.rds -> trained/evaluated Train_Model -> model_obj.rds
source(system.file("vignettes", "02_module2_modeling_QUICKSTART.R", package = "icare"))

# Module 3: stat_obj.rds -> NMF subtypes -> subtyping_obj.rds
source(system.file("vignettes", "03_module3_subtyping_QUICKSTART.R", package = "icare"))

# Module 4: your own time/status data.frame -> survival model + KM/risk groups
source(system.file("vignettes", "04_module4_survival_QUICKSTART.R", package = "icare"))

Each QUICKSTART script points to its ADVANCED counterpart for the full option set (multi-method feature selection, ensembling, tuning, SHAP/DALEX explanations, clinical thresholds & NRI/IDI, cluster cross-validation, survival benchmarking, decision-curve analysis, and the Shiny deployment apps).

Getting help

  • Function-level help: ?FunctionName inside R, or InspectObject(x) to inspect any icare S4 object's current state.
  • Bug reports and feature requests: please open a GitHub issue with a minimal reproducible example.

Citation

Luo H,Long F,Lin H,Jian H,Yu G. icare: Intelligent ClinlAbomics Research
Expedition. R package version 1.0.0.

License

GPL-3 © Huaichao Luo,Fei Long, Hongyan Lin,Jian Huang,Guangchuang Yu

About

Intelligent ClinlAbomics Research Expedition

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages