
Quick answer: Enrichment analysis asks a simple question about a long gene list: are genes with a shared function appearing more often than chance would produce? You bring a gene list, a set of gene sets (Gene Ontology terms, KEGG and Reactome pathways), and a background universe; the method counts the overlap and tests it. Two families dominate: over-representation analysis (ORA), which needs you to pick a cutoff and a background, and gene set enrichment analysis (GSEA), which ranks all genes and tests whether a set’s members cluster at one end of that ranking. Both are easy to run and easy to misread, because a significant term is a hypothesis about annotation, not proof of a mechanism.
A companion to the bulk RNA-seq analysis guide and the genome annotation guide: differential expression gives you the list, enrichment gives the list a biological reading.
Table of Contents
The four inputs you must choose deliberately
Almost every enrichment argument is really an argument about inputs:
- The gene list. The significant set from a statistical test. Its size is entirely a function of your cutoff, which is the first place results are manufactured.
- The gene sets. GO (three separate ontologies: Biological Process, Molecular Function, Cellular Component), KEGG pathways, or Reactome. These are curated annotations, so their completeness varies hugely by organism.
- The background universe. Every gene that could have appeared in your list. For RNA-seq this is the set of expressed genes, not the whole genome. This is the single most common modelling error.
- The statistic and correction. A hypergeometric or Fisher test for ORA, a rank-based enrichment score for GSEA, and a multiple-testing correction in both cases.
ORA, mechanically
ORA is a contingency table. Take a term with 40 genes, 300 genes in your list, and 60 of the term’s genes in your list, and ask how likely that overlap is when drawing 300 genes from a universe of 20,000. The test is hypergeometric, and the output is a p-value per term, corrected across all terms tested.
Its two knobs are what make it fragile. Lower the significance cutoff to 1.5-fold and the list doubles; run ORA on that list and different terms appear. Change the background from all annotated genes to expressed genes only and a whole class of terms gains or loses significance. So an ORA result is only interpretable alongside the cutoff and background stated with it.
GSEA, and why it exists
GSEA stops picking a cutoff. Rank every gene by its test statistic, then walk down that ranking and ask whether a term’s genes cluster near the top or bottom more than expected. The output is an enrichment score, a normalized version, and a false discovery rate. Because nothing is thresholded, a term that is coherent but made of individually weak changes can be detected — which is exactly the case ORA loses.
The trade is interpretability. GSEA reports a set and a direction, not a gene count, so “which genes drove this?” requires looking at the leading edge. That is a real cost, and the reason many papers report both.
| ORA | GSEA | |
|---|---|---|
| Input | A thresholded gene list | All genes, ranked |
| Catches weak coordinated shifts | No | Yes |
| Sensitive to an arbitrary cutoff | Yes, strongly | No |
| Needs a background universe | Yes | Implicitly, through the ranking |
| Typical use | Quick reading of a differential expression list | Confirming a coherent programme across many genes |
GO is three ontologies and a hierarchy
Beginners treat “GO analysis” as one test; it is three, and you must choose which. A gene can be significant for a Biological Process while nothing shows in Molecular Function, and reporting only one of them without saying so is a silent bias.
The hierarchy adds a second trap. GO terms nest: “immune response” sits above “innate immune response” and “adaptive immune response”, so a term and its child both being significant is usually one finding, not two. Tools that report the full table hand you a list dominated by related parents and children. The fixes are term-simplification steps (which drop redundant terms in favour of their most specific members) and semantic similarity clustering.
The gene-length and study bias nobody mentions
Two biases are built into the reference annotations themselves and are worth knowing before interpreting any table:
- Gene length bias. Longer genes have more reads, produce more statistical power, and therefore appear in differential expression lists more often — and therefore in GO terms that contain them. In RNA-seq, enrichment results partly reflect transcript length.
- Annotation bias. Well-studied genes are annotated more thoroughly. A popular gene is in many GO terms by construction, so pathways built around famous genes look enriched in studies that happen to include them.
Neither invalidates enrichment analysis, but both mean the honest claim is “genes with function X are over-represented in this list” rather than “function X is the mechanism”.
Running it
The R clusterProfiler ecosystem is the practical standard for reproducible analysis, with g:Profiler, Enrichr and DAVID as web alternatives for a quick look:
library(clusterProfiler)
library(org.Hs.eg.db)
# ORA against GO Biological Process, with an explicit universe
ego <- enrichGO(gene = sig_entrez,
universe = expressed_entrez, # expressed genes ONLY
OrgDb = org.Hs.eg.db,
ont = "BP",
keyType = "ENTREZID",
pAdjustMethod = "BH",
pvalueCutoff = 0.05,
qvalueCutoff = 0.05)
simplify(ego, cutoff = 0.7, by = "p.adjust", select_fun = min)
# GSEA on the full ranked list, no cutoff needed
gse <- gseGO(geneList = ranked_entrez,
OrgDb = org.Hs.eg.db,
ont = "BP",
keyType = "ENTREZID",
minGSSize = 10, maxGSSize = 500, pvalueCutoff = 0.05)The two details that separate a defensible run from a reportable accident are visible in that code: universe is set explicitly to the expressed genes, and the result is simplified before it is shown. Both are one line and both change the output.
How to read and report a result table
A useful result table has the term, the gene ratio (how many of the term’s genes are in your list), the count, the corrected p-value, and the direction. Report in this order:
- The input list and how it was defined (cutoff, test, correction).
- The background used.
- The ontology or pathway database and its version.
- Redundant terms simplified or clustered.
- The genes that drove each reported term.
Point 5 is the one that gets skipped, and it is the one that matters. A term reported without its member genes is an assertion nobody can check; a term reported with them is an observation someone can follow up.
Common failure modes
- Using the whole genome as the background for an RNA-seq experiment. Only expressed genes were candidates, so the genome background inflates significance.
- Reporting every term in the table. A list of two hundred enriched terms is not a result. Simplify, cluster, and report the coherent few.
- Testing all three GO ontologies separately and reporting whichever looks best. Decide which ontology answers the question, or state all three.
- Treating an enrichment p-value as a mechanism. Over-representation means the annotation set is non-random in your list, nothing more.
- Ignoring gene length and annotation bias. Both plausibly explain part of any human enrichment result.
- Skipping the correction. Hundreds or thousands of terms are tested; without multiple-testing correction the table is noise.
Key takeaways
- Enrichment analysis has two families: ORA with a cutoff, and GSEA on a full ranking; the choice depends on whether a coherent weak signal matters for your question.
- The background universe is the highest-impact decision in ORA, and for RNA-seq it must be the expressed genes rather than the whole genome.
- GO is three ontologies in a hierarchy, so redundancy between a term and its children must be simplified before reporting.
- Gene length and annotation bias are built into the references, so enrichment supports a hypothesis rather than proving a mechanism.
- A defensible report lists the input list, the background, the database, the correction, the simplification step, and the driving genes.
Challenge
Re-run one enrichment analysis you have already seen — or any published one — three times: once with a genome background, once with an expressed-gene background, and once simplified. Then write down which terms survived all three and which appeared only in the least careful run. The difference between those two lists is a precise measure of how much of a typical enrichment table is artefact of choices rather than biology.
Need help interpreting an enrichment analysis for a dissertation or manuscript? Ampersand Academy offers one-to-one mentoring in bioinformatics and data analysis — part of Mahadhi, a development and digital marketing company.
FAQ
What is the difference between GO and KEGG enrichment analysis?
GO describes gene function as three ontologies (biological process, molecular function, cellular component), while KEGG describes pathways. GO is broader and better annotated for non-model organisms; KEGG is more mechanistic but narrower and more human-centric.
What is the background gene set and why does it matter?
The background is every gene that could have appeared in your list. In RNA-seq that is the expressed genes, not the whole genome. Using the genome as background inflates significance and is the most common error in published enrichment analyses.
Should I use over-representation analysis or GSEA?
Use ORA for a quick reading of a thresholded list, and GSEA when you expect coherent but individually weak changes that a cutoff would discard. Many studies report both, because they answer slightly different questions.
Why do I get so many significant GO terms?
Because GO terms nest. A term and all its children can be significant for one underlying finding, and thousands of terms are tested at once. Simplify the result and correct for multiple testing before reading it.
Do I need to correct for multiple testing in enrichment analysis?
Yes. Hundreds or thousands of gene sets are tested, so a raw p-value cutoff of 0.05 produces a large number of false positives. Use a Benjamini-Hochberg style correction and report the adjusted value.
Can enrichment analysis tell me the mechanism behind my result?
No. It tells you which annotated gene sets appear more often than chance in your list, which is a hypothesis. Gene length and annotation bias mean the underlying cause still has to be tested experimentally.
Which tool should a beginner use for enrichment analysis?
clusterProfiler in R is the reproducible standard and handles GO, KEGG, GSEA and simplification in one place. Web tools such as g:Profiler and Enrichr are fine for a fast look but are harder to document in a methods section.
Last updated on · Written by Dinesh Kumar R
