Un tableau d'expressions différentielles (DEG) est un point de départ utile, mais ce n'est que rarement la fin de l'histoire. La plupart des gens se heurtent à la même question suivante : que signifient ces changements au niveau des gènes en ce qui concerne les voies et les fonctions biologiques ? C'est là qu'intervient l'analyse d'enrichissement fonctionnel.
Ce guide de style ressource présente un flux de travail complet et répétable en R : QC → normalisation → expression différentielle → enrichment (ORA et GSEA) → visualisation, en utilisant clusterProfiler (un package R de Bioconductor) pour l'enrichissement et les graphiques adaptés à l'enrichissement. Il est rédigé de manière à ce que vous puissiez copier la structure dans votre propre carnet d'analyse ou l'adapter en un petit script. Vous trouverez également un squelette de script R compact près de la fin.
En cours de route, nous nous concentrerons sur les détails pratiques qui ont tendance à être les plus importants dans les projets réels : les formats d'entrée, les identifiants de gènes, l'univers génétique de référence, comment choisir entre l'ORA et la GSEA, et comment réaliser les trois graphiques que les gens utilisent réellement (volcan + bar + point).
Si vous hésitez encore sur la manière de définir les seuils, d'interpréter le log2FC et le FDR, ou de structurer votre tableau de DEG pour une analyse ultérieure, vous pourriez trouver cet aperçu de l'expression différentielle utile : Analyse de l'expression génique différentielle.
Aperçu du flux de travail du pipeline d'enrichissement DEG basé sur clusterProfiler.
Une fois que vous aurez terminé ce flux de travail, vous devriez avoir un petit ensemble de résultats faciles à réutiliser et à partager :
Si vous rédigez un article de blog de style méthode ou un SOP interne, ces résultats s'intègrent parfaitement à une structure de dossier simple :
Option A : Commencer par les comptes (recommandé)
Vous avez :
C'est l'itinéraire le plus propre car vous contrôlez l'ensemble de la chaîne.
Option B : Commencer à partir d'un tableau DEG (le plus rapide)
Vous avez déjà des résultats de DESeq2/edgeR/limma :
C'est bien pour l'enrichissement tant que la table DEG est bien formée et que vous pouvez reconstruire un classement pour GSEA si vous le souhaitez.
Dans les flux de travail d'enrichissement, le moment le plus courant de "pourquoi est-ce vide ?" est un décalage d'ID.
Identifiants typiques que vous verrez :
clusterProfiler peut fonctionner avec plusieurs types, mais de nombreux flux de travail GO/KEGG sont plus simples si vous convertissez en ENTREZID pour l'enrichissement. L'approche pratique est :
Cette table de correspondance devient votre "colle" lorsque vous devez interpréter des résultats ou établir des listes de gènes pour une analyse ultérieure.
Une pile stable et courante ressemble à ceci :
Remarque : la disponibilité et le comportement de KEGG peuvent varier selon l'organisme et la manière dont les identifiants sont gérés. Si vous travaillez avec une espèce moins courante, GO peut être plus simple que KEGG, à moins que vous ne disposiez d'un bon soutien en annotation.
Le contrôle qualité ne doit pas être compliqué, mais il doit être intentionnel. L'objectif est simple : assurez-vous que vos échantillons se comportent comme votre conception d'étude l'attend.
Trois vérifications couvrent beaucoup de terrain :
L'ACP est rapide, visuelle et généralement informative.
Visualisation de contrôle qualité des échantillons basée sur l'ACP.
De petites différences sont normales. De grandes différences peuvent être un signe de problèmes techniques.
Une note pratique sur les valeurs aberrantes :
Si vous retirez un échantillon, notez-le. pourquoi En une phrase, et gardez une trace. Même pour un travail interne, votre futur vous vous en sera reconnaissant.
La normalisation est l'un de ces mots qui signifie des choses différentes selon les contextes.
Pour l'expression différentielle, la plupart des méthodes établies s'attendent à des comptes bruts et effectuent la normalisation dans le cadre du modèle :
Un détour fréquent consiste à utiliser TPM/FPKM pour l'analyse de l'expression différentielle (DE). Le TPM est utile pour certains types de comparaisons, mais pour l'analyse DE basée sur les comptes, il soulève généralement plus de questions qu'il n'apporte de réponses. Si votre objectif est un test différentiel fiable, restez dans la voie basée sur les comptes.
Un certain filtrage est utile :
Le filtrage améliore la puissance et réduit le bruit, en particulier dans les petites études.
Votre table DEG est le point de pivot entre les statistiques au niveau des gènes et l'enrichissement. Une "bonne" table DEG pour l'enrichissement en aval comprend :
Un point de départ commun est :
Mais de nombreuses analyses bénéficient d'une certaine flexibilité :
Si vous savez que votre signal est subtil (ou que votre taille d'échantillon est modeste), envisagez de vous appuyer davantage sur une GSEA basée sur le classement plutôt que d'essayer de "forcer" une grande liste de DEG.
Pour ORA, il est souvent utile de réaliser l'enrichissement séparément pour :
Cela maintient la clarté de la directionnalité. Sinon, vous pouvez vous retrouver avec un ensemble de gènes mélangé où un terme est "enrichi" mais les gènes qui le composent se déplacent dans les deux directions.
C'est le cœur du guide. clusterProfiler prend en charge plusieurs approches d'enrichissement, mais deux sont particulièrement courantes pour RNA-seq interprétation :
Entrées dont vous avez besoin
À propos de l'univers (ensemble de gènes de fond)
Si vous ne définissez pas un univers, votre enrichissement est souvent comparé à un large fond par défaut provenant de la base de données d'annotation. Dans de nombreux cas, un univers plus pratique et défendable est :
Cela aligne le fond d'enrichissement avec ce que votre expérience pourrait détecter de manière réaliste.
Enrichissement GO (point de départ recommandé)
Enrichissement KEGG (optionnel)
KEGG peut être très utile, mais c'est aussi là que les problèmes d'ID et d'organisme apparaissent plus souvent. Si KEGG renvoie des résultats vides :
GSEA modifie la question. Au lieu de sélectionner un "sous-ensemble de gènes significatifs", vous classez tous les gènes selon une statistique et vous demandez si les gènes d'une voie ont tendance à apparaître près du haut ou du bas.
Ce dont vous avez besoin pour GSEA
Classement des choix faciles à expliquer
Si vous choisissez l'approche des valeurs p signées, protégez-vous contre les zéros et les NA (par exemple, fixez les valeurs p à un minimum comme 1e-300).
Ce flux de travail se concentre intentionnellement sur trois graphiques car ils couvrent la plupart des besoins sans transformer votre rédaction en un musée de figures.
Un graphique en volcan montre :
Bonnes habitudes :
Graphique en volcan résumant les résultats de l'expression différentielle.
Utilisez des diagrammes à barres pour montrer une courte liste des termes les plus enrichis. Restez concis :
Les dotplots sont un excellent résumé en "un seul panneau" :
Si vous publiez des dotplots, veillez à ce que la légende soit lisible et évitez de montrer trop de termes.
Diagramme à points résumant les termes fonctionnels enrichis avec un encodage par taille et couleur.
Cette section est destinée à être une liste de contrôle rapide "avant d'exporter les résultats".
Astuce : exportez un tableau de correspondance et conservez-le avec vos résultats. Cela évite la confusion par la suite.
Si les résultats d'ORA semblent étranges (trop larges, trop vides, trop génériques), revoyez l'univers.
Un défaut pratique :
Si vous n'êtes pas satisfait des résultats d'ORA, essayez GSEA avant de réécrire vos seuils cinq fois.
GO est par nature hiérarchique et redondant. Si vos meilleurs résultats ressemblent à des répétitions :
Raisons courantes :
Un graphique techniquement correct peut néanmoins être difficile à lire.
Voici un squelette de script compact que vous pouvez adapter. Il suppose :
C'est intentionnellement minimal afin que vous puissiez l'intégrer dans un téléchargement de ressource de blog et laisser les lecteurs modifier quelques lignes.
suppressPackageStartupMessages({
bibliothèque(DESeq2)
bibliothèque(clusterProfiler)
bibliothèque(enrichplot)
bibliothèque(AnnotationDbi)
library(org.Hs.eg.db) # remplacez par votre organisme
bibliothèque(ggplot2)
bibliothèque(dplyr)
})
# ---- Entrées (modifier) ----
counts_file <- "counts.csv" # gènes x échantillons, comptes bruts
meta_fichier <- "meta.csv" # échantillon, condition (et lot optionnel)
id_type_in <- "SYMBOLE" # SYMBOLE ou ENSEMBL
cond_a <- "traité"
cond_b <- "contrôle"
dir.create("tables", showWarnings = FALSE)
dir.create("plots", showWarnings = FALSE)
# ---- Charger ----
counts <- read.csv(fichier_counts, row.names = 1, check.names = FALSE)
meta <- read.csv(meta_file, stringsAsFactors = FALSE)
counts <- counts[, meta$échantillon]
# ---- FR ----
dds <- DESeqDataSetFromMatrix(
countData = arrondi(as.matrix(counts)),
colData = data.frame(meta, row.names = meta$échantillon),
design = ~ condition
)
# Filtrage simple
dds <- dds[rowSums(counts(dds) >= 10) >= 2, ]
dds <- DESeq(dds)
res <- résultats(dds, contraste = c("condition", cond_a, cond_b))
res <- as.data.frame(res) %>%
muter(gène = rownames(.)) %>%
filtrer(!est.na(padj))
write.csv(res, "tables/DEG_results.csv", row.names = FALSE)
# ---- Volcan ----
vol <- res %>% mutate(sig = padj < 0,05 & abs(log2FoldChange) >= 1)
p_vol <- ggplot(vol, aes(log2FoldChange, -log10(padj))) +
geom_point(aes(alpha = sig), size = 1) +
scale_alpha_manual(values = c(`VRAI` = 0.8, `FAUX` = 0.2), guide = "aucune") +
theme_bw() +
labs(x = "Changement de Fold log2", y = "-log10(FDR)", title = "Diagramme de volcan")
ggsave("plots/volcano.pdf", p_vol, width = 6.5, height = 5)
# ---- Mappage d'ID ----
mapped <- bitr(res$gene,
fromType = id_type_in,
toType = "ENTREZID",
OrgDb = org.Hs.eg.db)
res_entrez <- res %>%
inner_join(mapped, by = c("gene" = id_type_in)) %>%
distinct(ENTREZID, .keep_all = TRUE)
write.csv(res_entrez, "tables/DEG_with_ENTREZID.csv", row.names = FALSE)
write.csv(mapped, "tables/ID_mapping.csv", row.names = FALSE)
# ---- ORA (GO BP) ----
deg_up <- res_entrez %>% filtrer(padj < 0.05, log2FoldChange >= 1) %>% tirer(ENTREZID)
deg_dn <- res_entrez %>% filtrer(padj < 0.05, log2FoldChange <= -1) %>% tirer(ENTREZID)
univers <- res_entrez$ENTREZID
ego_up <- enrichGO(gene = deg_up, univers = univers,
OrgDb = org.Hs.eg.db, typeDeClé = "ENTREZID",
ont = "BP", méthodePAdj = "BH", seuilQvalue = 0.05)
ego_dn <- enrichGO(gène = deg_dn, univers = univers,
OrgDb = org.Hs.eg.db, typeDeClé = "ENTREZID",
ont = "BP", méthodePAdj = "BH", seuilQvalue = 0,05)
write.csv(as.data.frame(ego_up), "tables/GO_ORA_up.csv", row.names = FALSE)
write.csv(as.data.frame(ego_dn), "tables/GO_ORA_down.csv", row.names = FALSE)
# ---- Graphiques : barres + points ----
ggsave("plots/GO_ORA_up_bar.pdf", barplot(ego_up, showCategory = 15), width = 7, height = 5)
ggsave("plots/GO_ORA_up_dot.pdf", dotplot(ego_up, showCategory = 15), width = 7, height = 5)
# ---- Optionnel : GSEA ----
rank_vec <- res_entrez$stat
si (tous(est.na(rank_vec))) {
p <- pmax(res_entrez$pvalue, 1e-300)
rank_vec <- signe(res_entrez$log2FoldChange) * -log10(p)
}
noms(rank_vec) <- res_entrez$ENTREZID
rank_vec <- sort(rank_vec, decreasing = TRUE)
gse_bp <- gseGO(listeDeGènes = rank_vec,
OrgDb = org.Hs.eg.db, typeDeClé = "ENTREZID",
ont = "BP", pAdjustMethod = "BH", verbose = FALSE)
write.csv(as.data.frame(gse_bp), "tables/GO_GSEA_BP.csv", row.names = FALSE)
ggsave("plots/GO_GSEA_dot.pdf", dotplot(gse_bp, showCategory = 15), width = 7, height = 5)
Comment transformer cela en une ressource téléchargeable.
Dois-je exécuter DESeq2 pour utiliser clusterProfiler ?
Non. Vous pouvez utiliser clusterProfiler avec les résultats de n'importe quelle méthode d'analyse différentielle, tant que vous avez une liste de gènes pour l'ORA ou un vecteur de gènes classés pour le GSEA.
Devrais-je utiliser ORA ou GSEA pour l'enrichissement des voies ?
Utilisez ORA lorsque vous souhaitez une enrichissement sur un ensemble de DEG sélectionné. Utilisez GSEA lorsque vous préférez tester l'enrichissement sur une liste classée sans vous fier à un seuil strict.
Pourquoi l'enrichissement ne renvoie-t-il aucun résultat ?
Le plus souvent, il s'agit d'un décalage entre l'ID et l'organisme (surtout pour KEGG) ou la liste d'entrée est trop petite. Vérifier la conversion des ID et passer à GSEA sont des solutions courantes.
Quel ensemble de gènes de fond (univers) devrais-je utiliser pour l'ORA ?
Un défaut pratique est l'ensemble des gènes testés dans votre analyse DE (après filtrage), et non l'ensemble du génome.
Combien de termes devrais-je tracer ?
En général, 10 à 20 termes suffisent pour une figure claire ; davantage tend à devenir répétitif et difficile à lire.
Références :