| Title: | Label-Switch Classification for Baseline- and Perturbation-Aligned Features |
|---|---|
| Description: | Quantifies baseline-aligned and perturbation-aligned molecular features across biological perturbations using a label-switch classification framework. Provides a unified workflow for identifying changes in molecular-feature alignment in longitudinal or comparative omics datasets. Includes tools for classification, visualization, dimension reduction, and pathway enrichment. |
| Authors: | Di Xiao [aut, cre], Pengyi Yang [aut] |
| Maintainer: | Di Xiao <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.99.1 |
| Built: | 2026-09-18 10:30:05 UTC |
| Source: | https://github.com/BiocStaging/SwitchClass |
Q1: delta > T & FC > 0 Q2: delta < -T & FC > 0 Q3: delta < -T & FC < 0 Q4: delta > T & FC < 0 Q0: otherwise
assign_quadrants(delta, fc, delta_thresh = 0.15)assign_quadrants(delta, fc, delta_thresh = 0.15)
delta |
named numeric vector (features). |
fc |
named numeric vector (same feature names as |
delta_thresh |
numeric threshold for |delta|. |
factor vector of quadrant labels with names = features.
delta <- c(a = 0.2, b = -0.2, c = -0.2, d = 0.2, e = 0) fc <- c(a = 1, b = 1, c = -1, d = -1, e = 1) assign_quadrants(delta, fc, delta_thresh = 0.15)delta <- c(a = 0.2, b = -0.2, c = -0.2, d = 0.2, e = 0) fc <- c(a = 1, b = 1, c = -1, d = -1, e = 1) assign_quadrants(delta, fc, delta_thresh = 0.15)
A small example dataset from the colorectal cancer (CRC) plasma proteome study. It contains a pre-filtered expression matrix and sample group labels (HC = healthy control, Pre = pre-treatment, Post = post-treatment).
data(CRC_subset)data(CRC_subset)
A list with two elements:
A numeric matrix of features (rows) × samples (columns).
A character vector of sample groups, length = ncol(expr).
The data are a subset of the discovery cohort used in the SwitchClass analysis.
Useful for testing or demonstrating functions such as label_switch_classify().
Internal preprocessed subset from Li et al. 2024, Nat Commun.
data(CRC_subset) dim(CRC_subset$expr) table(CRC_subset$group)data(CRC_subset) dim(CRC_subset$expr) table(CRC_subset$group)
Wraps a convenience pipeline:
builds Reactome TERM2GENE via msigdbr
runs pathwayOverrepresent on each quadrant (Q1..Q4)
returns top-k barplots (-log10 p) and tidy tables
enrich_reactome_quadrants( df, universe, species = "Homo sapiens", top_terms = 5, palette = c(Q1 = "#33DBB2", Q2 = "#DFB647", Q3 = "#2ECEF8", Q4 = "#76CF49") )enrich_reactome_quadrants( df, universe, species = "Homo sapiens", top_terms = 5, palette = c(Q1 = "#33DBB2", Q2 = "#DFB647", Q3 = "#2ECEF8", Q4 = "#76CF49") )
df |
data.frame with columns |
universe |
character vector of background gene symbols (e.g., rownames(discovery.cohort)) |
species |
msigdbr species (default "Homo sapiens") |
top_terms |
how many top terms per quadrant to plot (default 5) |
palette |
named colors for bars of Q1..Q4 |
list with:
named list of data.frames p1..p4 (or NULL if no hits)
tidy data.frame used for plotting
ggpubr patch of 4 panels
Trains two random-forest classifiers under baseline-aligned and
perturbation-aligned label schemes, then returns the directional importance
score using
MeanDecreaseGini importances.
label_switch_classify( X, y_reverse, y_persist, ntimes = 25, seed = 1, ntree = 1000, mtry = NULL, parallel = FALSE, ncores = parallel::detectCores() - 1L )label_switch_classify( X, y_reverse, y_persist, ntimes = 25, seed = 1, ntree = 1000, mtry = NULL, parallel = FALSE, ncores = parallel::detectCores() - 1L )
X |
numeric matrix with features in rows and samples in columns. |
y_reverse |
character/factor labels (length = ncol(X)) for the baseline-aligned label scheme. The argument name is retained for compatibility with earlier package versions. |
y_persist |
character/factor labels (length = ncol(X)) for the perturbation-aligned label scheme. The argument name is retained for compatibility with earlier package versions. |
ntimes |
integer; number of RF repeats to average (default 25). |
seed |
integer; base seed (default 1). |
ntree |
integer; trees per forest (default 1000). |
mtry |
integer or NULL; variables tried at each split (default NULL). |
parallel |
logical; use multicore (default FALSE). |
ncores |
integer; cores if |
list with named numeric vectors: delta, importance_baseline,
importance_perturbation, plus compatibility aliases I_rev and I_per.
X <- matrix(seq_len(60) / 10, nrow = 10) rownames(X) <- paste0("feature", seq_len(nrow(X))) y_baseline <- rep(c("c1", "c2", "c1"), each = 2) y_perturbation <- rep(c("c1", "c2", "c2"), each = 2) res <- label_switch_classify( X, y_baseline, y_perturbation, ntimes = 1, ntree = 5 ) head(res$delta)X <- matrix(seq_len(60) / 10, nrow = 10) rownames(X) <- paste0("feature", seq_len(nrow(X))) y_baseline <- rep(c("c1", "c2", "c1"), each = 2) y_perturbation <- rep(c("c1", "c2", "c2"), each = 2) res <- label_switch_classify( X, y_baseline, y_perturbation, ntimes = 1, ntree = 5 ) head(res$delta)
Builds a tidy data.frame with quadrants and returns the ggplot scatter.
plot_delta_vs_fc( delta, fc, delta_thresh = 0.15, label_top = 5, label_size = 3, palette = c(Q1 = "#2E8B57", Q2 = "#C0392B", Q3 = "#C0392B", Q4 = "#2E8B57", Q0 = "grey70"), point_size = 2.2, alpha = 0.85, xlab = expression(delta), ylab = expression(log[2] * " FC"), title = "feature importance vs log2 fold-change" )plot_delta_vs_fc( delta, fc, delta_thresh = 0.15, label_top = 5, label_size = 3, palette = c(Q1 = "#2E8B57", Q2 = "#C0392B", Q3 = "#C0392B", Q4 = "#2E8B57", Q0 = "grey70"), point_size = 2.2, alpha = 0.85, xlab = expression(delta), ylab = expression(log[2] * " FC"), title = "feature importance vs log2 fold-change" )
delta |
named numeric vector of directional importance scores (features). |
fc |
named numeric vector of log2 fold-change (same names as |
delta_thresh |
numeric; absolute delta threshold to define Q1-Q4 (default 0.15). |
label_top |
integer; number of labels per quadrant (by absolute delta). Set 0 to skip. |
label_size |
numeric; text size for labels. |
palette |
named colors for quadrants. Names should include Q1..Q4 and optional Q0. |
point_size |
numeric; scatter point size. |
alpha |
numeric from 0 to 1; point transparency. |
xlab, ylab
|
axis labels. |
title |
plot title. |
list with elements: data (data.frame) and plot (ggplot object).
delta <- c(a = 0.2, b = -0.2, c = -0.2, d = 0.2, e = 0) fc <- c(a = 1, b = 1, c = -1, d = -1, e = 1) out <- plot_delta_vs_fc(delta, fc, label_top = 0) head(out$data) out$plotdelta <- c(a = 0.2, b = -0.2, c = -0.2, d = 0.2, e = 0) fc <- c(a = 1, b = 1, c = -1, d = -1, e = 1) out <- plot_delta_vs_fc(delta, fc, label_top = 0) head(out$data) out$plot
Boxplots for selected features across groups
plot_feature_boxplots( X, group, features, feature_order = NULL, palette = NULL, ncol = 4, add_jitter = TRUE, jitter_width = 0.15, notch = FALSE, free_y = TRUE, point_size = 1.6, box_linewidth = 0.4, title = NULL, ylab = "log2 expression", xlab = NULL, save_path = NULL, width = 7, height = 4.5 )plot_feature_boxplots( X, group, features, feature_order = NULL, palette = NULL, ncol = 4, add_jitter = TRUE, jitter_width = 0.15, notch = FALSE, free_y = TRUE, point_size = 1.6, box_linewidth = 0.4, title = NULL, ylab = "log2 expression", xlab = NULL, save_path = NULL, width = 7, height = 4.5 )
X |
numeric matrix with features in rows and samples in columns. |
group |
factor/character of length ncol(X) giving sample groups. |
features |
character vector of feature (gene/protein) names to plot. |
feature_order |
optional character vector to set facet order (defaults to |
palette |
optional named vector of group colors; if NULL, generated automatically. |
ncol |
integer; facets per row (default 4). |
add_jitter |
logical; add jittered points (default TRUE). |
jitter_width |
numeric; jitter width (default 0.15). |
notch |
logical; use notched boxplots (default FALSE). |
free_y |
logical; facet with free y scales (default TRUE). |
point_size |
numeric; jitter point size (default 1.6). |
box_linewidth |
numeric; box outline width (default 0.4). |
title, ylab, xlab
|
plot labels. |
save_path |
optional file path to save (pdf/png) using |
width, height
|
numeric dimensions (inches) if saving. |
ggplot object.
X <- matrix(seq_len(40) / 10, nrow = 5) rownames(X) <- paste0("feature", seq_len(nrow(X))) group <- rep(c("A", "B"), each = 4) plot_feature_boxplots(X, group, features = rownames(X)[1:2], ncol = 2)X <- matrix(seq_len(40) / 10, nrow = 5) rownames(X) <- paste0("feature", seq_len(nrow(X))) group <- rep(c("A", "B"), each = 4) plot_feature_boxplots(X, group, features = rownames(X)[1:2], ncol = 2)
Generates a standardized heatmap of feature expression grouped by quadrant (Q1-Q4) and sample group (e.g., HC / Pre / Post). Quadrants are optionally filtered by delta cutoff thresholds.
plot_heatmap_quadrants( X, group, df_quad, cutoff = 0.15, palette_group = NULL, palette_quad = NULL, scale = TRUE, cap = 2, show_rownames = TRUE, show_colnames = TRUE, cluster_rows = FALSE, cluster_cols = FALSE )plot_heatmap_quadrants( X, group, df_quad, cutoff = 0.15, palette_group = NULL, palette_quad = NULL, scale = TRUE, cap = 2, show_rownames = TRUE, show_colnames = TRUE, cluster_rows = FALSE, cluster_cols = FALSE )
X |
numeric matrix with features in rows and samples in columns. |
group |
factor/character of length = ncol(X); sample group labels. |
df_quad |
data.frame with columns: |
cutoff |
numeric; delta threshold for selecting strong quadrant features (default 0.15).
Quadrants Q1 and Q4 use |
palette_group |
optional named color vector for sample groups. |
palette_quad |
optional named color vector for quadrants. |
scale |
logical; z-score features (default TRUE). |
cap |
numeric; cap scaled values at +/- cap (default 2). |
show_rownames, show_colnames
|
logical; show labels (default TRUE). |
cluster_rows, cluster_cols
|
logical; cluster rows/columns (default FALSE). |
Invisibly returns the pheatmap object.
plot_heatmap_quadrants( X = matrix( seq_len(24), nrow = 4, dimnames = list(paste0("feature", 1:4), paste0("sample", 1:6)) ), group = rep(c("A", "B"), each = 3), df_quad = data.frame( feature = paste0("feature", 1:4), quadrant = c("Q1", "Q2", "Q3", "Q4"), delta = c(0.2, -0.2, -0.2, 0.2) ), show_rownames = FALSE, show_colnames = FALSE )plot_heatmap_quadrants( X = matrix( seq_len(24), nrow = 4, dimnames = list(paste0("feature", 1:4), paste0("sample", 1:6)) ), group = rep(c("A", "B"), each = 3), df_quad = data.frame( feature = paste0("feature", 1:4), quadrant = c("Q1", "Q2", "Q3", "Q4"), delta = c(0.2, -0.2, -0.2, 0.2) ), show_rownames = FALSE, show_colnames = FALSE )
Quick ggplot for UMAP embedding
plot_umap( emb, groups, title = "", point_size = 3, shape = 21, color = "black", stroke = 1.1, alpha = 0.9, palette = NULL )plot_umap( emb, groups, title = "", point_size = 3, shape = 21, color = "black", stroke = 1.1, alpha = 0.9, palette = NULL )
emb |
matrix from |
groups |
vector of sample groups (length = nrow(emb)). |
title |
character; plot title. |
point_size |
numeric; point size (default 3). |
shape |
integer; point shape (default 21 = filled circle). |
color, stroke, alpha
|
aesthetics for outlines and transparency. |
palette |
optional named vector of fill colors; if NULL, generated automatically. |
ggplot object.
emb <- matrix(c(0, 0, 1, 1, 0, 1), ncol = 2, byrow = TRUE) rownames(emb) <- paste0("sample", seq_len(nrow(emb))) plot_umap(emb, groups = c("A", "A", "B"))emb <- matrix(c(0, 0, 1, 1, 0, 1), ncol = 2, byrow = TRUE) rownames(emb) <- paste0("sample", seq_len(nrow(emb))) plot_umap(emb, groups = c("A", "A", "B"))
UMAP on samples using selected features
run_umap_samples( X, feats, n_neighbors = 15, min_dist = 0.1, metric = "euclidean", seed = 1 )run_umap_samples( X, feats, n_neighbors = 15, min_dist = 0.1, metric = "euclidean", seed = 1 )
X |
numeric matrix with features in rows and samples in columns. |
feats |
character; feature names to use (non-matching are ignored with a message). |
n_neighbors |
integer; UMAP neighbor size (default 15). |
min_dist |
numeric; UMAP min_dist (default 0.1). |
metric |
character; distance metric (default "euclidean"). |
seed |
integer; RNG seed for reproducibility (default 1). |
matrix with samples in rows and two UMAP columns, with rownames = sample IDs.
X <- matrix(seq_len(80) / 10, nrow = 10) rownames(X) <- paste0("feature", seq_len(nrow(X))) colnames(X) <- paste0("sample", seq_len(ncol(X))) emb <- run_umap_samples(X, rownames(X)[1:4], n_neighbors = 3) head(emb)X <- matrix(seq_len(80) / 10, nrow = 10) rownames(X) <- paste0("feature", seq_len(nrow(X))) colnames(X) <- paste0("sample", seq_len(ncol(X))) emb <- run_umap_samples(X, rownames(X)[1:4], n_neighbors = 3) head(emb)
Generates UMAPs for (1) baseline-aligned (+delta), (2) perturbation-aligned (-delta), and (3) all features. Returns the three embeddings and a combined plot.
umap_triptych_by_delta( X, delta, groups, top_n = 100, n_neighbors = 15, min_dist = 0.1, metric = "euclidean", seed = 1, palette = NULL )umap_triptych_by_delta( X, delta, groups, top_n = 100, n_neighbors = 15, min_dist = 0.1, metric = "euclidean", seed = 1, palette = NULL )
X |
numeric matrix with features in rows and samples in columns. |
delta |
named numeric vector of delta scores (names = feature IDs). |
groups |
factor or character of sample groups (length = ncol(X)). |
top_n |
integer; number of features to use per side (default 100). |
n_neighbors, min_dist, metric, seed
|
passed to |
palette |
optional named color vector for groups; if NULL, generated automatically. |
list with emb_baseline, emb_perturbation, emb_all, and plot.
X <- matrix(seq_len(100) / 10, nrow = 10) rownames(X) <- paste0("feature", seq_len(nrow(X))) colnames(X) <- paste0("sample", seq_len(ncol(X))) delta <- stats::setNames(seq(-1, 1, length.out = nrow(X)), rownames(X)) groups <- rep(c("A", "B"), each = 5) triptych <- umap_triptych_by_delta( X, delta, groups, top_n = 2, n_neighbors = 3 ) names(triptych)X <- matrix(seq_len(100) / 10, nrow = 10) rownames(X) <- paste0("feature", seq_len(nrow(X))) colnames(X) <- paste0("sample", seq_len(ncol(X))) delta <- stats::setNames(seq(-1, 1, length.out = nrow(X)), rownames(X)) groups <- rep(c("A", "B"), each = 5) triptych <- umap_triptych_by_delta( X, delta, groups, top_n = 2, n_neighbors = 3 ) names(triptych)