GSEA, GSVA and ssGSEA

· 7 min read · Analysis Notes

GSEA, GSVA and ssGSEA

TL;DR: Three complementary gene set enrichment methods: GSEA compares two conditions, GSVA transforms expression to pathway scores across samples, ssGSEA scores pathways per individual sample. Choose based on your experimental design and question.


What is Gene Set Enrichment Analysis?

Instead of analyzing individual genes, gene set methods test whether groups of related genes (pathways, GO terms) show coordinated changes. This:

  • Increases statistical power (biological signal > individual gene noise)
  • Provides mechanistic insights (pathways, not just gene lists)
  • Enables cross-study comparisons at the pathway level

GSEA Concept


Method Comparison

Method Input Requirement Output Use Case Supervised?
GSEA Ranked gene list + 2 groups NES, p-value, FDR Compare conditions Yes
GSVA Expression matrix (no groups) Per-sample pathway scores Unsupervised clustering No
ssGSEA Expression matrix (no groups) Per-sample enrichment scores Sample-level profiling No

Quick Decision Guide

Do you have two groups to compare? 
├─ YES → Use GSEA
└─ NO → Do you want pathway-based clustering?
    ├─ YES → Use GSVA
    └─ NO → Need per-sample scores? → Use ssGSEA

Method 1: GSEA (Gene Set Enrichment Analysis)

Purpose

Test whether a pre-defined gene set is enriched at the top or bottom of a ranked gene list comparing two conditions.

When to Use

  • ✅ Differential expression between two groups (disease vs. control, treated vs. untreated)
  • ✅ You have enough replicates for statistical testing
  • ✅ Want to identify pathways driving the difference

Input Requirements

  1. Normalized expression matrix
  2. Phenotype labels (group A vs. group B)
  3. Gene sets (e.g., MSigDB, GO, KEGG)

Running GSEA in R

library(fgsea)
library(msigdbr)

# 1. Prepare ranked gene list (from DESeq2, edgeR, etc.)
res <- results(dds, contrast = c("condition", "treated", "control"))
gene_ranks <- res$log2FoldChange
names(gene_ranks) <- rownames(res)
gene_ranks <- sort(gene_ranks, decreasing = TRUE)

# 2. Load gene sets (Hallmark pathways from MSigDB)
hallmark <- msigdbr(species = "Homo sapiens", category = "H")
pathways <- split(hallmark$gene_symbol, hallmark$gs_name)

# 3. Run GSEA
fgsea_res <- fgsea(
  pathways = pathways,
  stats = gene_ranks,
  minSize = 15,
  maxSize = 500,
  nperm = 10000
)

# 4. View significant pathways
fgsea_res %>%
  filter(padj < 0.05) %>%
  arrange(NES) %>%
  select(pathway, NES, padj, size)

Interpretation

Metric Meaning
NES > 0 Gene set enriched in group A (upregulated)
NES < 0 Gene set enriched in group B (downregulated)
** NES
padj < 0.05 Statistically significant

Example:
NES = 2.3, padj = 0.001 for "HALLMARK_INFLAMMATORY_RESPONSE" → Strong upregulation of inflammatory genes in treated samples.


Method 2: GSVA (Gene Set Variation Analysis)

Purpose

Transform gene expression into pathway-level scores for each sample, enabling unsupervised analysis and sample clustering.

When to Use

  • ✅ No predefined groups (exploratory analysis)
  • ✅ Want to cluster samples by pathway activity
  • ✅ Correlate pathways with continuous clinical variables

Running GSVA in R

library(GSVA)
library(limma)

# 1. Prepare expression matrix (log2 TPM/CPM)
expr_matrix <- assay(vst(dds))  # Variance-stabilized counts

# 2. Load gene sets
pathways <- getGmt("c2.cp.kegg.v7.5.symbols.gmt")  # KEGG pathways

# 3. Run GSVA
gsva_scores <- gsva(
  expr_matrix,
  pathways,
  method = "gsva",
  kcdf = "Gaussian",  # Use "Poisson" for count data
  min.sz = 10,
  max.sz = 500,
  verbose = TRUE
)

# 4. Differential pathway analysis
design <- model.matrix(~ condition, data = colData(dds))
fit <- lmFit(gsva_scores, design)
fit <- eBayes(fit)
topTable(fit, coef = "conditiontreated", number = 10)

# 5. Heatmap of pathway scores
pheatmap(gsva_scores, 
         annotation_col = data.frame(condition = colData(dds)$condition),
         scale = "row")

Output Interpretation

  • Positive score: Pathway activity higher than average across samples
  • Negative score: Pathway activity lower than average
  • Use for: Clustering samples, correlating with metadata

Method 3: ssGSEA (Single-Sample GSEA)

Purpose

Calculate enrichment scores for each gene set within individual samples, useful for single-sample predictions or heterogeneous datasets.

When to Use

  • ✅ Single sample or very small N
  • ✅ Sample-specific pathway profiling (e.g., tumor subtyping)
  • ✅ Building pathway-based classifiers

Running ssGSEA in R

library(GSVA)

# 1. Prepare expression matrix
expr_matrix <- assay(vst(dds))

# 2. Run ssGSEA
ssgsea_scores <- gsva(
  expr_matrix,
  pathways,
  method = "ssgsea",  # Key difference from GSVA
  ssgsea.norm = TRUE,  # Normalize scores
  verbose = TRUE
)

# 3. Example: Score a new sample
new_sample <- read.csv("new_sample.csv")
new_scores <- gsva(
  as.matrix(new_sample),
  pathways,
  method = "ssgsea"
)

# 4. Compare to reference cohort
reference_mean <- rowMeans(ssgsea_scores)
deviation <- new_scores - reference_mean

ssGSEA vs GSVA

Feature GSVA ssGSEA
Algorithm Kernel smoothing Sample-wise ranking
Normalization Across samples Within sample
Best for Group comparisons Individual profiling

Other Methods

PLAGE (Pathway Level Analysis)

Uses singular value decomposition (SVD) to summarize gene set expression:

plage_scores <- gsva(
  expr_matrix,
  pathways,
  method = "plage"
)

Best for: Reducing dimensionality while preserving pathway structure.

Z-score Method

Simple standardized mean:

zscore_scores <- gsva(
  expr_matrix,
  pathways,
  method = "zscore"
)

Best for: Quick exploratory analysis.


Practical Workflow

Step 1: Choose Gene Sets

Source Description Size
MSigDB Hallmark 50 well-defined processes Curated, minimal overlap
KEGG ~300 pathways Metabolic + signaling
GO Biological Process ~7,000 terms Comprehensive but redundant
Reactome ~2,000 pathways Detailed, hierarchical
# Download via msigdbr
library(msigdbr)

# Hallmark (recommended starting point)
hallmark <- msigdbr(species = "Homo sapiens", category = "H")

# KEGG
kegg <- msigdbr(species = "Homo sapiens", category = "C2", subcategory = "CP:KEGG")

# GO Biological Process
go_bp <- msigdbr(species = "Homo sapiens", category = "C5", subcategory = "GO:BP")

Step 2: Preprocessing

# Filter low-expressed genes
keep <- rowSums(counts(dds) >= 10) >= 3
dds <- dds[keep,]

# Normalize
vsd <- vst(dds, blind = FALSE)  # Or rlog()

Step 3: Run Analysis

# For group comparison: GSEA
fgsea_res <- fgsea(pathways, gene_ranks)

# For unsupervised: GSVA
gsva_scores <- gsva(assay(vsd), pathways)

# For single samples: ssGSEA
ssgsea_scores <- gsva(assay(vsd), pathways, method = "ssgsea")

Step 4: Visualization

# GSEA enrichment plot
plotEnrichment(pathways[["HALLMARK_HYPOXIA"]], gene_ranks)

# GSVA heatmap
pheatmap(gsva_scores, scale = "row", clustering_distance_rows = "correlation")

# Pathway bar plot
top_pathways <- fgsea_res %>% filter(padj < 0.05) %>% top_n(20, abs(NES))
ggplot(top_pathways, aes(x = reorder(pathway, NES), y = NES, fill = NES > 0)) +
  geom_col() +
  coord_flip() +
  labs(title = "Top Enriched Pathways")

Troubleshooting

"No pathways significant in GSEA"

Possible causes:

  • Small effect sizes
  • Not enough replicates
  • Wrong gene ID format

Fix:

# Check gene ID conversion
sum(names(gene_ranks) %in% unlist(pathways))  # Should be >80%

# Relax FDR threshold for exploratory analysis
filter(fgsea_res, pval < 0.05)

GSVA scores all near zero

Cause: Expression data not properly normalized
Fix: Use variance-stabilized or log2-transformed data, not raw counts

Memory errors with large gene sets

Fix:

# Reduce gene set size
filtered_pathways <- pathways[sapply(pathways, length) < 500]

# Or use parallel processing
gsva(..., parallel.sz = 4)

Comparison Summary

Choose GSEA if:

  • You have two groups and sufficient replicates
  • Want to identify pathways driving condition differences
  • Need statistical significance testing

Choose GSVA if:

  • Exploratory analysis without predefined groups
  • Want to cluster samples by pathway activity
  • Correlating pathways with continuous variables

Choose ssGSEA if:

  • Single-sample predictions
  • Building pathway-based classifiers
  • Heterogeneous datasets (e.g., tumor samples)

Resources


See also:


Originally posted on WeChat Official Account: bioinfo_studyroom

GSEA Pathway Analysis