Gene Ontology over-representation analysis (ORA) tests whether a gene LIST is enriched for genes annotated to each GO term, using the one-sided hypergeometric (Fisher 2x2) test in clusterProfiler's enrichGO. The single decision that governs the result is the BACKGROUND universe: ORA is a competitive test comparing the foreground against the rest of the measured genome, so the universe IS the null distribution. Pick the genes that could have entered the list (the tested-gene set), not the whole genome, or every p-value is wrong in a direction that cannot be seen.
if (!require('BiocManager', quietly = TRUE))
install.packages('BiocManager')
BiocManager::install(c('clusterProfiler', 'org.Hs.eg.db'))
BiocManager::install('goseq') # only for RNA-seq gene-length bias correction
Conceptual prerequisites: - The input is a pre-selected gene LIST plus a matched BACKGROUND universe. A ranked vector of all genes with no cutoff is a GSEA input instead (see the gsea skill). - The universe must be the genes that could have been selected (RNA-seq: genes that passed filtering / have a non-NA DESeq2 pvalue; proteomics: detected proteins; targeted panel: panel genes), mapped with the same ID call as the foreground. Omitting the universe defaults it to all annotated genes and inflates significance. - enrichGO's source default is ont='MF', not 'BP' - set ont explicitly every time. - pvalueCutoff filters the adjusted p (p.adjust), not the raw p; an empty result usually means the cutoff or the universe, not biology. - GO annotation is local (org.*.eg.db + GO.db, pinned to the Bioconductor release), so a GO ORA is reproducible given the package versions - no internet needed at runtime. - The DE list and the significance threshold that defines the foreground come from differential-expression; this skill consumes them.
Tell your AI agent what you want to do: - "Run GO enrichment on my differentially expressed genes with the tested genes as background" - "Which biological processes are over-represented in this gene list?" - "Simplify the redundant GO terms and show fold enrichment, not just p-values" - "My data is RNA-seq - correct for gene length bias with GOseq"
"I have 240 significant genes from a DESeq2 contrast (padj < 0.05, |log2FC| > 1) as gene symbols, and the ~13,000 expressed genes as the background. Run GO BP over-representation with the expressed genes as the universe, simplify the redundant terms, and give me the top 15 by adjusted p-value with fold enrichment."
"Run GO enrichment for all three ontologies (BP, MF, CC) on this gene list and simplify each ontology separately."
"I have a full ranked DESeq2 result with the test statistic for every gene and no clear significance cutoff. Should I run ORA or GSEA, and run whichever is appropriate on GO terms."
"Run GO enrichment separately for the upregulated and downregulated genes and report both."
"This is RNA-seq and I am worried about long-gene bias - run length-corrected GO enrichment with GOseq."
"Run an over-representation test of my gene list against these MSigDB hallmark sets with my expressed genes as background."
| Column | Description |
|---|---|
| ID | GO term ID (GO:XXXXXXX) |
| Description | GO term name |
| GeneRatio | k/n = foreground genes in term / foreground genes annotated to any term |
| BgRatio | M/N = universe genes in term / universe genes annotated to any term |
| pvalue | Raw hypergeometric p-value |
| p.adjust | BH-adjusted p-value (this is what pvalueCutoff filters) |
| qvalue | Q-value |
| geneID | Genes in the term |
| Count | k = number of foreground genes in the term |
Fold enrichment = GeneRatio / BgRatio. Both denominators are restricted to ANNOTATED genes.
| Ontology | Code | Description |
|---|---|---|
| Biological Process | BP | what the genes participate in |
| Molecular Function | MF | biochemical activity (the enrichGO default) |
| Cellular Component | CC | where in the cell |
enrichment_force_universe option keeps unannotated genes in the universe instead of intersecting with annotated genes; the intersection is usually the desired behavior for GO (an unannotated gene can never be a hit), so use the option only to match another tool's denominator.