Un análisis de enriquecimiento funcional suele aplicarse para extraer información biológica relevante, ya sea de una lista filtrada de genes relevantes o bien de todo el genoma evaluado por un valor estadístico.
El ejemplo más conocido de esta lista podría ser la lista filtrada de genes diferencialmente expresados (por algún punto de corte de logFold Change) o bien la lista de todos los genes estimado por su valor de logFold Change.
Si bien hay varios métodos para hacer enriquecimiento1, los dós métodos más comunes son el Análisis de sobrerepresentación (Over-representation analysis o ORA) y el Análisis de Enriquecimiento de Conjuntos de Genes (Gene Set Enrichment Analysis o GSEA). Ambos incluidos en clusterProfiler
.
Análisis | Lo que require de entrada | Como luce la salida | ✅ Pros | |
---|---|---|---|---|
ORA (Over-representation Analysis) | Una lista de genes (no se requeiren estadísticos) | Una prueba hipergeométrica por vía | - Sencillo - Barato computacionalmente para calcular p-values |
- Ignora estadísticas asociadas con los genes y requiere puntos de corte arbitrarios - Asume independencia de genes y pathways |
GSEA (Gene Set Enrichment Analysis) | Una lista de IDs de genes con un valor estadístico por gen | Un puntaje de enriquecimiento (enrichment score ES) por vía | - Incluye todos los genes (Sin puntos de corte arbitrarios) |
- Las permutaciones pueden ser computacionalmente costosas - No considera sobrelape de vías |
Herramienta en linea para hacer ORA https://maayanlab.cloud/Enrichr/
#BiocManager::install("clusterProfiler")
library(clusterProfiler)
library(tidyverse)
Vamos a usar los genes diferencialmente expresados del trabajo The regulatory landscape of retinoblastoma: a pathway analysis perspective, por lo que usaremos la anotación de humano "org.Hs.eg.db". Puedes ver las anotaciones disponibles aquí.
#BiocManager::install("org.Hs.eg.db", character.only = TRUE)
library("org.Hs.eg.db", character.only = TRUE)
# Lectura de la tabla de genes diferencialemente expresados
degs = readRDS("data/degs.RDS")
# necesitamos el log2 fold change
original_gene_list <- degs$logFC
# Nombramos el vector
names(original_gene_list) <- degs$ESGN
# eliminamos cualquier NA
gene_list<-na.omit(original_gene_list)
# odernamos la lista en orden decreciente (requerido por clusterProfiler)
gene_list = sort(gene_list, decreasing = TRUE)
# extraemos los genes significativos (p ajustada < 0.05)
sig_genes_df = subset(degs, adj.P.Val < 0.05)
# para los resultados significativos, queremos filtrar por log2fold change
genes <- sig_genes_df$logFC
# nombramos el vector
names(genes) <- sig_genes_df$ESGN
# omitimos posibles NAs
genes <- na.omit(genes)
# filtramos por mínimo log2fold change (log2FoldChange > 2)
genes <- names(genes)[abs(genes) > 2]
Parámetros:
ont Ontología de GO a utilizar. Opciones: "BP", "MF" o "CC"
keyType Esta puede variar depepndiendo de la anotación (gene ids). Por ejemplo para "org.Hs.eg.db", las opciones son:
"ACCNUM" "ALIAS" "ENSEMBL" "ENSEMBLPROT" "ENSEMBLTRANS" "ENTREZID" "ENZYME" "EVIDENCE" "EVIDENCEALL" "GENENAME" "GENETYPE" "GO" "GOALL" "IPI" "MAP" "OMIM" "ONTOLOGY" "ONTOLOGYALL" "PATH" "PFAM" "PMID" "PROSITE" "REFSEQ" "SYMBOL" "UCSCKG" "UNIPROT"
Puedes checar las opciones de la anotación de tu organismo usando la función keytypes
, por ejemplo keytypes(org.Hs.eg.db)
.
go_enrich <- enrichGO(gene = genes,
universe = names(gene_list),
OrgDb = org.Hs.eg.db,
keyType = 'ENSEMBL',
readable = TRUE,
ont = "BP",
pvalueCutoff = 0.05,
qvalueCutoff = 0.10)
head(go_enrich)
Enfatiza el sobrelape de genes a lo largo de los diferentes set de genes.
#BiocManager::install("enrichplot")
library(enrichplot)
upsetplot(go_enrich)
barplot(go_enrich,
drop = TRUE,
showCategory = 10,
title = "GO Biological Pathways",
font.size = 8)
dotplot(go_enrich)
Si queremos enriquecer patways de KEGG necesitamos convertir los ids para poder usar la función gseKEGG()
. Para ello podemos usar la función bitr
que está incluida el clusterProfiler
. Es normal que algunos mensajes y warnings salgan al usar esta función.
En la función bitr
, el parámetro fromType
debe ser el tipo de keyType
del de la función gseGO
que vimos anteriormente (la fuente original). Este parámetro es usado dos veces más la crear los dedup_ids
y el degs2
.
El otro parámetro toType
en la función bitr
también debe ser otra de las anitaciones disponibles el keyTypes("org.Hs.eg.db")
y debe mapear a alguna de 'kegg', 'ncbi-geneid', 'ncbi-proteinid' o 'uniprot' porque la función gseKEGG()
solo acepta alguna de estas 4 opciones como entrara en el parámetro keytype
. En el caso de org.Hs.eg.db usaremos 'ENTREZID' para toType
, ya que este se corresponde con el ncbi-geneid y tiene mejor match con 'ENSEMBL', pero podríamos también usar 'UNIPROT'.
Como nuestra entrada inicial usaremos nuestra original_gene_list
que creamos para el enriquecimiento en GO.
# Convertimos los gene IDs para la función enrichKEGG
# Podría ser que perdamos algunos genes aquí dado que algunas conversiones no son compatibles
ids<-bitr(names(original_gene_list), fromType = "ENSEMBL", toType = "ENTREZID", OrgDb="org.Hs.eg.db")
# Removemos IDS duplicados (aquí se usa "ENSEMBL", pero debería de ser lo que hayamos usado como keyType)
dedup_ids = ids[!duplicated(ids[c("ENSEMBL")]),]
# Creamos un nuevo dataframe df2 el cual solo tiene genes que se an convertido exitosamente usando la función bitr
degs2 = degs[degs$ESGN %in% dedup_ids$ENSEMBL,]
# Creamos una nueva columna en degs2 con los ENTREZ ids correspondientes
degs2$Y = dedup_ids$ENTREZID
# Creamos un vector de genes del universo
kegg_gene_list <- degs2$logFC
# Nombramos el vector con los ENTREZ ids
names(kegg_gene_list) <- degs2$Y
# Verificamos que no haya NAs
kegg_gene_list<-na.omit(kegg_gene_list)
# Ordenamos la lista en orden decreciente (requerido por for clusterProfiler)
kegg_gene_list = sort(kegg_gene_list, decreasing = TRUE)
# Extraemos los resultados significativos del degs2
kegg_sig_genes_degs = subset(degs2, adj.P.Val < 0.05)
# También filtraremos por log2fold change
kegg_genes <- kegg_sig_genes_degs$logFC
# Nombramos el vector con los IDs convertidos
names(kegg_genes) <- kegg_sig_genes_degs$Y
# eliminanmos NAs
kegg_genes <- na.omit(kegg_genes)
# Y ahora si filtramos por log2fold change
kegg_genes <- names(kegg_genes)[abs(kegg_genes) > 2]
Parámetros:
organism código KEGG del organismo: La lista completa está aquí: https://www.genome.jp/kegg/catalog/org_list.html (se necesita el código de 3 letras). En el caso del humano es "hsa"
keyType one of 'kegg', 'ncbi-geneid', 'ncib-proteinid' or 'uniprot'.
kk <- enrichKEGG(gene=kegg_genes,
universe=names(kegg_gene_list),
organism="hsa",
pvalueCutoff = 0.05,
keyType = "ncbi-geneid")
head(kk)
barplot(kk,
showCategory = 10,
title = "Enriched Pathways",
font.size = 8)
dotplot(kk,
showCategory = 10,
title = "Enriched Pathways",
font.size = 8)
Con este paquete se puede visualizar nuestros genes en las vías de KEGG generando una imagen PNG y un PDF diferente.
Parámetros:
gene.data Esta es la lista gene_list
creada arriba, el tipo de ids tiene que coincidir con el de gene.idtype
pathway.id Tenemos que elegir aquí nosotros alguna. Como la idea es visualizar nuestras vías significativamente enriquecidas, pordemos usar los ids de los pathways que nos sale en head(kk)
.
species El id de organism
de la función enrichKEGG
, en este caso "hsa"
gene.idtype el tipo de ids utilizados en gene.data
pero sacado del objeto gene.idtype.list
. En este caso tomamos el tercer elemento de esta lista.
#BiocManager::install("pathview")
library(pathview)
# Produce una gráfica de KEGG (PNG)
hsa <- pathview(gene.data=gene_list, pathway.id="hsa04740", species = "hsa", gene.idtype=gene.idtype.list[3])
# Produce una gráfica diferente (PDF)
hsa <- pathview(gene.data=gene_list, pathway.id="hsa04740", species = "hsa", gene.idtype=gene.idtype.list[3], kegg.native = FALSE)
Las imágenes se salvan en su directorio de trabajo.
#BiocManager::install("clusterProfiler")
#BiocManager::install("pathview")
#BiocManager::install("enrichplot")
library(clusterProfiler)
library(enrichplot)
library(ggplot2)
Vamos a usar, de nuevo, los genes diferencialmente expresados del este lindo trabajo The regulatory landscape of retinoblastoma: a pathway analysis perspective. Por lo que usaremos la anotación de humano "org.Hs.eg.db" de nuevo. Recuerden que la lista completa está aquí.
#BiocManager::install("org.Hs.eg.db", character.only = TRUE)
library("org.Hs.eg.db", character.only = TRUE)
# Lectura de la tabla de genes diferencialemente expresados
degs = readRDS("data/degs.RDS")
# necesitamos el log2 fold change
original_gene_list <- degs$logFC
# Nombramos el vector
names(original_gene_list) <- degs$ESGN
# eliminamos cualquier NA
gene_list<-na.omit(original_gene_list)
# odernamos la lista en orden decreciente (requerido por clusterProfiler)
gene_list = sort(gene_list, decreasing = TRUE)
Parámetros:
keyType Igual que en el ORA, el tipo de ids utilizados en nuestra lista. Receurden que los tipos permitidos se enlistan con el comado keytypes("org.Hs.eg.db")
. Recueden que si usan algo distinto a Humano deben cambiar su anotación.
ont Ontología. Alguno de "BP" (procesos biológicos), "MF" (función molecular), "CC" (componente celular) o "ALL" (todas)
minGSSize tamaño mínimo de geneSet para analizar.
maxGSSize tamaño máximo de genes anotados para probar.
pvalueCutoff punto de corte del p-value.
pAdjustMethod metodo para ajustar la p, puede ser uno de estos: "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none"
gse <- gseGO(geneList=gene_list,
ont ="ALL",
keyType = "ENSEMBL",
minGSSize = 3,
maxGSSize = 800,
pvalueCutoff = 0.05,
verbose = TRUE,
OrgDb = "org.Hs.eg.db",
pAdjustMethod = "BH")
Noten que hemos dado toda la lista de genes con su valor de lofFC. Estás enriqueciendo sin un criterio arbitrario (elegido por nosotros), puro dato duro y maduro.
head(gse)
#BiocManager::install("DOSE")
require(DOSE)
dotplot(gse, showCategory=10, split=".sign") + facet_grid(.~.sign)
Agrupados por pathways, se generan gráficos de densidad utilizando la frecuencia del logFold Change por gen dentro de cada set. Útil para interpretar vías reguladas al alza o a la baja.
ridgeplot(gse) + labs(x = "enrichment distribution")
Método tradicional para visualizar resultados de GSEA.
Parámetros:
GeneSetID Entero. Corresponde al pathway en el objeto 'gse'. El primero pathway es el 1, el segundo el 2, etc.
# Usamos el objeto 'geneset' para que siempre coincidan el título y el gene set correspondiente.
geneset = 1
gseaplot(gse, by = "all", title = gse$Description[geneset], geneSetID = geneset)
Para hacer GSEA con KEGG usaremos la función gseKEGG()
y tambien cambiaremmos de tipos de ids con bitr
como en ORA (arriba).
Como input inicial usaremos original_gene_list
que creamos para GSEA de GO.
# Convertir genes IDs para la función gseKEGG
# Podría ser que se perdieran algunos genes por la conversión
ids<-bitr(names(original_gene_list), fromType = "ENSEMBL", toType = "ENTREZID", OrgDb="org.Hs.eg.db")
# se elimnan ids duplicados (aquí usamos "ENSEMBL", pero debemos usar lo que hayamos empleado en el argumento "fromType")
dedup_ids = ids[!duplicated(ids[c("ENSEMBL")]),]
# Creamos un nuevo dataframe degs2 en cual solo contiene los genes que hicieron match usando ña función bitr
degs2 = degs[degs$ESGN %in% dedup_ids$ENSEMBL,]
# Creamos una nueva coñumna en degs2 con los correspondientes ENTREZ IDs
degs2$Y = dedup_ids$ENTREZID
# Creamos un vector con el universo de genes
kegg_gene_list <- degs2$logFC
# Nombramos el vector con los ENTREZ ids
names(kegg_gene_list) <- degs2$Y
# eliminamos NAs
kegg_gene_list<-na.omit(kegg_gene_list)
# Ordenamos los datos en orden decreciente (requerido por clusterProfiler)
kegg_gene_list = sort(kegg_gene_list, decreasing = TRUE)
Parámetros:
organism Cómo en el ORA (arriba) código del organismo de KEGG. En este caso también "hsa" de humano. Lista completa: https://www.genome.jp/kegg/catalog/org_list.html (need the 3 letter code).
ont Ontología. Alguno de "BP" (procesos biológicos), "MF" (función molecular), "CC" (componente celular) o "ALL" (todas)
minGSSize tamaño mínimo de geneSet para analizar.
maxGSSize tamaño máximo de genes anotados para probar.
pvalueCutoff punto de corte del p-value.
pAdjustMethod metodo para ajustar la p, puede ser uno de estos: "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none"
kk2 <- gseKEGG(geneList = kegg_gene_list,
organism = "hsa",
minGSSize = 3,
maxGSSize = 800,
pvalueCutoff = 0.05,
pAdjustMethod = "none",
keyType = "ncbi-geneid")
head(kk2, 10)
dotplot(kk2, showCategory = 10, title = "Enriched Pathways" , split=".sign") + facet_grid(.~.sign)
Como en GSEA GO, útil para interpretar vías reguladas al alza o a la baja.
ridgeplot(kk2) + labs(x = "enrichment distribution")
Método tradicional para visualizar resultados de GSEA.
Parámetros:
GeneSetID Entero. Corresponde al pathway en el objeto 'gse'. El primero pathway es el 1, el segundo el 2, etc.
# Usamos el objeto 'geneset' para que siempre coincidan el título y el gene set correspondiente.
geneset = 1
gseaplot(kk2, by = "all", title = gse$Description[geneset], geneSetID = geneset)
Obviamente podemos usar Pathview para mapear los pathways que salieron significativamente representados en nuestro GSEA.
Parámetros:
gene.data Esta es la lista gene_list
creada arriba, el tipo de ids tiene que coincidir con el de gene.idtype
pathway.id Tenemos que elegir aquí nosotros alguna. Como la idea es visualizar nuestras vías significativamente enriquecidas, pordemos usar los ids de los pathways que nos sale en head(kk2, 10)
.
species El id de organism
de la función enrichKEGG
, en este caso "hsa"
gene.idtype el tipo de ids utilizados en gene.data
pero sacado del objeto gene.idtype.list
. En este caso tomamos el tercer elemento de esta lista.
#BiocManager::install("pathview")
library(pathview)
# Produce una gráfica de KEGG (PNG) Usaremos hsa05322 proque el primer pathway más enriquecido fue el mismo que graficamos arriba
hsa <- pathview(gene.data=gene_list, pathway.id="hsa05322", species = "hsa", gene.idtype=gene.idtype.list[3])
# Produce una gráfica diferente (PDF)
hsa <- pathview(gene.data=gene_list, pathway.id="hsa05322", species = "hsa", gene.idtype=gene.idtype.list[3], kegg.native = FALSE)
Las imágenes se salvan en su directorio de trabajo.
Tutorial: https://alexslemonade.github.io/refinebio-examples/03-rnaseq/pathway-analysis_rnaseq_01_ora.html
artículo "Pathway size matters: the influence of pathway granularity on over-representation (enrichment analysis) statistics" https://bmcgenomics.biomedcentral.com/articles/10.1186/s12864-021-07502-8
Tutorial "Functional Analysis for RNA-seq" https://hbctraining.github.io/DGE_workshop_salmon_online/lessons/10_FA_over-representation_analysis.html