Version Compatibility
Reference examples tested with: MOFA2 1.12+, mixOmics 6.26+, SNFtool 2.3+, clusterProfiler 4.10+, ggplot2 3.5+
Before using code patterns, verify installed versions match. If versions differ:
- R:
packageVersion('<pkg>') then ?function_name to verify parameters
If code throws ImportError, AttributeError, or TypeError, introspect the installed
package and adapt the example to match the actual API rather than retrying.
Multi-omics Integration Pipeline
"Integrate my multi-omics datasets" -> Decide the strategy first, then orchestrate harmonization, the chosen integration method (MOFA2, mixOmics, or SNF), interpretation, and validation - because bulk multi-omics is small-n, huge-p, so an unvalidated integrated result is the default noise outcome.
Before any tool runs, settle the design with multi-omics-integration/integration-design: confirm the data is vertical (different omics on the SAME samples, not the same features across cohorts), map the question to a method (shared factors -> MOFA2, predictive signature -> DIABLO, patient subtypes -> SNF), and plan a held-out cohort because in-cohort cross-validation at small n is optimistically biased. Inspect the per-view variance-explained table to confirm no single omic dominates the shared structure.
The governing principle
Bulk multi-omics is small-n, huge-p, so an UNVALIDATED integrated result is the DEFAULT noise outcome, not the exception. Every honesty decision is made at a seam before the integrator runs.
- The sample-matching key must be VERTICAL, and joined on a stable primary key. Vertical = different features, SAME samples (what this category is FOR); horizontal (same features, different cohorts) is meta-analysis/batch, a different problem — conflating them is the deepest category error. The shared latent factor is indexed by SAMPLE, so establish the subject primary key ONCE and externalize it (MAE
sampleMap / consistent MuData obs_names); NEVER cbind/pd.concat on assumed row order (silently mis-pairs subjects). Gene SYMBOLS are display labels, not join keys (MARCH1->MARCHF1, Excel corruption) — join on stable Ensembl IDs.
- Each omic is normalized in its OWN space FIRST, then block variance is equalized BEFORE stacking. A shared-latent integrator decomposes total variance and assumes each feature is ~continuous/Gaussian; the non-negotiable per-omic transforms (RNA-seq -> VST/logCPM never raw counts; methylation -> M-values; prot/metab -> log2 + MNAR-aware; microbiome -> CLR) come first, then per-VIEW scaling (MOFA
scale_views=TRUE) equalizes each block's CONTRIBUTION. Variance is additive across features, so a block with more features (850k CpGs vs 100 metabolites) casts more votes and hijacks the shared space regardless of biological importance. Both failures are silent.
- No factor/subtype/signature is credible until it reproduces in a HELD-OUT cohort. In-cohort CV at n<<p is optimistically biased (tuning feature selection on the full data then reporting same-data CV inflates AUC by up to ~0.15); the gold standard is an external test set or fully nested CV. Spurious cross-omic correlation is the DEFAULT at p>>n. Batch is corrected ONCE, in ONE place (ComBat each omic AND modeling batch downstream removes it twice and over-shrinks real biology).
The single best honesty check: if every shared factor is dominated by one view, the pipeline did not integrate — it re-discovered the biggest omic.
Made-once commitments
| Commitment | Consequence inherited downstream |
|---|
| Correspondence axis (VERTICAL, not horizontal) | Whether the integrator's math has anything to align on; conflating the two is the deepest category error |
| Sample primary key (externalized in MAE/MuData) | Correct subject-to-assay linkage; cbind-on-row-order silently mis-pairs subjects |
| Per-block normalization + per-view variance scaling | Whether the widest omic hijacks every factor; done before stacking, never after |
| Validation plan (held-out cohort) | Whether any factor/signature is credible; in-cohort CV at n<<p is optimistically biased |
Pipeline Overview
RNA-seq Data ─────┐
│
Proteomics Data ──┼──> Data Harmonization ──> Integration ──> Factors/Components
│ │
Metabolomics ─────┘ ▼
┌─────────────────────────────────────────────────────┐
│ multi-omics-pipeline │
├─────────────────────────────────────────────────────┤
│ 1. Data Preprocessing per Modality │
│ 2. Sample Harmonization (matching samples) │
│ 3. Feature Selection/Filtering │
│ 4. Integration (MOFA2 / mixOmics / SNF) │
│ 5. Factor/Component Interpretation │
│ 6. Downstream Analysis │
└─────────────────────────────────────────────────────┘
│
▼
Integrated Factors + Biomarker Signatures
Complete MOFA2 Workflow
Goal: Discover unsupervised shared and view-specific factors across the harmonized omics, then interpret and validate them.
Approach: Harmonize to common samples, feature-select per view, train MOFA2, read the per-view variance decomposition first, label factors against biological and technical covariates, and run enrichment on the signed weights.
library(MOFA2)
library(MOFAdata)
library(ggplot2)
library(tidyverse)
rna <- read.csv('rnaseq_normalized.csv', row.names = 1)
cat('RNA:', nrow(rna), 'samples,', ncol(rna), 'genes\n')
protein <- read.csv('proteomics_normalized.csv', row.names = 1)
cat('Protein:', nrow(protein), 'samples,', ncol(protein), 'proteins\n')
metab <- read.csv( row.names
cat nrowmetab ncolmetab
common_samples Reduceintersect rownamesrna rownamesprotein rownamesmetab
cat common_samples
rna rnacommon_samples
protein proteincommon_samples
metab metabcommon_samples
select_variable data n
vars applydata var na.rm
top_features sortvars decreasing n ncoldata
data top_features
rna_var select_variablerna n
protein_var select_variableprotein n
metab_var select_variablemetab n
data_list
RNA tas.matrixrna_var
Protein tas.matrixprotein_var
Metabolome tas.matrixmetab_var
mofa create_mofadata_list
sample_metadata read.csv
rownamessample_metadata sample_metadatasample_id
sample_metadatasample sample_metadatasample_id
samples_metadatamofa sample_metadatacommon_samples
data_opts get_default_data_optionsmofa
data_optsscale_views
model_opts get_default_model_optionsmofa
model_optsnum_factors 15
train_opts get_default_training_optionsmofa
train_optsmaxiter 1000
train_optsconvergence_mode
train_optsseed 42
mofa prepare_mofamofa data_options data_opts
model_options model_opts
training_options train_opts
cat
mofa run_mofamofa outfile use_basilisk
plot_variance_explainedmofa max_r2
ggsave width height
factor_values get_factorsmofa
correlate_factors_with_covariatesmofa covariates
plot_factormofa factors color_by dot_size
ggsave width height
f
cat f
weights get_weightsmofa factors f as.data.frame
view uniqueweightsview
view_weights weightsweightsview view
view_weights view_weightsorderview_weightsvalue decreasing
cat view pasteheadview_weightsfeature collapse
plot_top_weightsmofa view factors nfeatures
ggsave width height
libraryclusterProfiler
libraryorg.Hs.eg.db
rna_weights get_weightsmofa views factors
top_genes sortrna_weights decreasing
all_rna_genes rna_weights
ego enrichGOgene top_genes
universe all_rna_genes
OrgDb org.Hs.eg.db
keyType
ont
pvalueCutoff
ego simplifyego cutoff by
dotplotego showCategory
ggsave width height
librarysurvival
librarysurvminer
surv_data data.frame
sample rownamesfactor_values
factor1 factor_values
time sample_metadatarownamesfactor_values
status sample_metadatarownamesfactor_values
surv_datafactor1_group ifelsesurv_datafactor1 mediansurv_datafactor1
fit survfitSurvtime status factor1_group data surv_data
ggsurvplotfit data surv_data pval risk.table
ggsave width height
write.csvfactor_values
all_weights get_weightsmofa as.data.frame
write.csvall_weights row.names
cat
mixOmics DIABLO Workflow
Goal: Build a supervised cross-omic signature that discriminates a known outcome, with an honest performance estimate.
Approach: Set the design matrix from the goal, tune the component count then keepX inside cross-validation folds with balanced error rate, fit, and report performance from data not used in tuning.
library(mixOmics)
X <- list(
RNA = as.matrix(rna_var),
Protein = as.matrix(protein_var),
Metabolome = as.matrix(metab_var)
)
Y <- factor(sample_metadata[common_samples, 'condition'])
design <- matrix(0.5, ncol = length(X), nrow = length(X),
dimnames = list(names(X) X
diagdesign
perf.diablo perfblock.splsdaX Y ncomp design design
validation folds nrepeat
ncomp perf.diablochoice.ncompWeightedVote
cat ncomp
test.keepX
RNA
Protein
Metabolome
tune.diablo tune.block.splsdaX Y ncomp ncomp test.keepX test.keepX
design design validation folds
optimal.keepX tune.diablochoice.keepX
diablo.model block.splsdaX Y ncomp ncomp
keepX optimal.keepX design design
plotIndivdiablo.model ind.names legend title
plotVardiablo.model var.names style legend
circosPlotdiablo.model cutoff line
color.blocks
cimDiablodiablo.model color.blocks
margins
perf.final perfdiablo.model validation folds nrepeat
perf.finalWeightedVote.error.rate
auc.diablo aurocdiablo.model roc.block roc.comp
Similarity Network Fusion (SNF)
Goal: Stratify patients into candidate subtypes from the fused multi-omic similarity network.
Approach: Standardize each omic, build local-scaled affinity networks, fuse by cross-diffusion, estimate a plausible cluster number, and defend it with a fused-versus-single-omic concordance check before claiming subtypes.
library(SNFtool)
K <- 20
sigma <- 0.5
views <- lapply(list(rna_var, protein_var, metab_var), function(x) standardNormalization(as.matrix(x)))
affinities <- lapply(views, function(x) affinityMatrix(dist2(x, x)^(1/2), K, sigma))
W <- SNF(affinities, K, t = 20
estimateNumberOfClustersGivenGraphW NUMC
clusters spectralClusteringW K
concordanceNetworkNMIaffinities W
displayClustersWithHeatmapW clusters
QC Checkpoints
| Stage | Check | Action if Failed |
|---|
| Sample matching | >80% samples shared | Check sample IDs |
| Missing values | <20% per modality | Impute or remove |
| Feature variance | Features vary | Filter low variance |
| Model convergence | ELBO plateau | Increase iterations |
| Factor variance | drop factors below ~1-2% in all views | set drop_factor_threshold; keep fewer factors |
| Variance imbalance | no single view dominates every factor | per-view scaling or filter the wider view harder |
| Validation | held-out cohort, not in-cohort CV | replicate before claiming a biomarker/subtype |
Workflow Variants
With Missing Samples
to_long <- function(mat, view) {
df <- as.data.frame(as.table(as.matrix(mat)))
data.frame(sample = as.character(df$Var1), feature = as.character(df$Var2), view = view, value = df$Freq)
}
data_long <- rbind(to_long(rna, 'RNA'), to_long(protein, 'Protein'))
mofa <- create_mofa_from_df(data_long)
Single-cell Multi-omics
Single-cell multimodal data (CITE-seq, 10x Multiome) is a different paradigm - per-cell generative models with abundant observations rather than the bulk small-n regime. Route it to single-cell/multimodal-integration rather than applying this bulk pipeline.
Common Errors
| Symptom | Cause | Fix |
|---|
| Integrated result on mislabeled subjects (both axes have plausible lengths) | cbind/pd.concat on assumed sample order | Enforce sample linkage via a container (MAE sampleMap / MuData intersect_obs); assert shape after every cross-language hop |
| One view dominates every factor | Block scale/feature-count imbalance (850k CpGs vs 100 metabolites) | Per-VIEW scaling (scale_views=TRUE), NOT per-feature; filter larger views harder; check per-(factor,view) R2 |
| A near-constant noise feature blown up to variance 1 | Per-feature scaling (scale=TRUE in mixOmics) | Aggressive low-variance filtering BEFORE scaling; prefer per-view scaling |
| A "biological" factor that is really batch | Technical variance not regressed out | Correlate every factor with technical covariates (run date, plate, site); exclude a factor tracking batch more than biology |
| AUC inflated by up to ~0.15 | In-cohort CV with feature selection outside the folds | CV must WRAP selection (nested); gold standard is an external test set (predict()/auroc()) |
| Batch removed twice, real biology over-shrunk | ComBat each omic AND batch in the downstream model | Correct batch ONCE: pre-correct and do not re-enter, OR leave raw and model batch as a covariate |
| Transposed matrices make every gene a "sample" | Bioconductor (samples=cols) vs mixOmics/MOFA (samples=rows) mismatch | Transpose deliberately + assert shape on every cross-package hop |
References
- Argelaguet R, Velten B, Arnol D, et al (2018) Multi-Omics Factor Analysis - a framework for unsupervised integration of multi-omics data sets. Molecular Systems Biology 14:e8124. DOI 10.15252/msb.20178124. (MOFA.)
- Rohart F, Gautier B, Singh A, Le Cao KA (2017) mixOmics: an R package for 'omics feature selection and multiple data integration. PLoS Computational Biology 13:e1005752. DOI 10.1371/journal.pcbi.1005752.
- Singh A, Shannon CP, Gautier B, et al (2019) DIABLO: an integrative approach for identifying key molecular drivers from multi-omics assays. Bioinformatics 35:3055-3062. DOI 10.1093/bioinformatics/bty1054.
- Wang B, Mezlini AM, Demir F, et al (2014) Similarity network fusion for aggregating data types on a genomic scale. Nature Methods 11:333-337. DOI 10.1038/nmeth.2810. (SNF.)
- Rappoport N, Shamir R (2018) Multi-omic and multi-view clustering algorithms: review and cancer benchmark. Nucleic Acids Research 46:10546-10562. DOI 10.1093/nar/gky889. (integration is not automatically better than the best single omic.)
- Nygaard V, Rodland EA, Hovig E (2016) Methods that remove batch effects while retaining group differences may lead to exaggerated confidence in downstream analyses. Biostatistics 17:29-39. DOI 10.1093/biostatistics/kxv027.
Related Skills
- multi-omics-integration/integration-design - Method selection, correspondence, and the n<<p discipline (decide first)
- multi-omics-integration/mofa-integration - MOFA2 unsupervised factor analysis
- multi-omics-integration/mixomics-analysis - mixOmics DIABLO/sPLS/MINT methods
- multi-omics-integration/similarity-network - SNF patient stratification
- multi-omics-integration/data-harmonization - Cross-omic preprocessing and scaling
- pathway-analysis/go-enrichment - Factor/signature interpretation
- differential-expression/batch-correction - Batch effects
- clinical-biostatistics/survival-analysis - Survival validation of factors and subtypes
- single-cell/multimodal-integration - Single-cell multimodal integration (different paradigm)