En esta parte del curso vamos a realizar lo sigueinte:
- Construcción de objetos necesarios para llevar a cabo la expresión diferencial
- Ensayo de expresión diferencial
- Obtener los genes diferencialmente expresados
- Diversos métodos de visualización
- Enriquecimiento de genes
- Análisis de sobrerepresenctación (ORA)
- GSEA
Para consultar la parte teórica revisar la explicación.
💡
La documentación aquí mostrada es una adapatación de información en línea y de cursos previos de la Dra. Alejandra Cervera y el Dr. Hugo Tovar. https://github.com/hachepunto/bioinformatics/blob/master/presentaciones/5-tximport.md
Entrar a la carpeta del drive, descarga el archivo salida_kallisto.zip descomprimirlo detro de datos.taller. Se encuentran 6 carpetas de salida de Kallisto en las dos condiciones, también se incluyen 4 archivos de texto donde se incluyen la información de la localización de las muestras y archivo de referencia del cromosoma 22, con tres columnas, el Id del gen, las diversas variantes de splicing y su símbolo.
Los datos de prueba consisten en dos muestras de ARN disponibles comercialmente: Referencia Humana Universal (UHR) y Referencia de Cerebro Humano (HBR). La UHR es ARN total aislado de un conjunto diverso de 10 líneas celulares cancerosas (mama, hígado, cuello uterino, testículo, cerebro, piel, tejido adiposo, histiocito, macrófago, célula T, célula B). La HBR es ARN total aislado de los cerebros de 23 caucásicos, hombres y mujeres, de diversas edades, pero en su mayoría de 60 a 80 años.
Para generar los diversos archivos de texto, mismos que ya están contenidos dentro de la Terminal de RStudio ejecutar
ls ./datos.taller/salida_kallisto_*/abundance.tsv | cut -d"/" -f3 | cut -d"_" -f3-4 > ./datos.taller/ids.txt ##### HBR_Rep1
ls ./datos.taller/salida_kallisto_*/abundance.tsv | cut -d"/" -f3 | cut -d"_" -f3 > ./datos.taller/condicion.txt #### HBR, UHR
ls ./datos.taller/salida_kallisto_*/abundance.tsv > ./datos.taller/rutas.txt ### paths
paste ids.txt condicion.txt rutas.txt > ./datos.taller/mis_muestras.tsv
Para empezar a crear un script con todos los pasos que vamos a ejecutar, abran en Rstudio un Rscript: File -> New File -> Rscript Es necesario y fundamental guardar el script, lo pueden hacer con CTRL+s o COMMAND+S, también dando con File -> Save. Asignen el nombre de DGEA.R
De manera inicial vamos a realizar todas las instalaciones necesario de las librerías a ocupar
### Instalaciones
if (!require("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install(version = "3.19")
BiocManager::install("S4Arrays")
BiocManager::install("tximport")
### DGEA
BiocManager::install("DESeq2")
### Volcano plots
BiocManager::install("EnhancedVolcano")
### GSEA
BiocManager::install("clusterProfiler")
### GSEA Plot
BiocManager::install("enrichplot",force = TRUE)
### GSEA Plot
BiocManager::install("DOSE",force = T)
### Gene reference
BiocManager::install("org.Hs.eg.db", character.only = TRUE)
### heatmaps, ORA
install.packages(c("pheatmap","ggplot2", "enrichR"))
💡 NOTA
Las instalaciones sólo es necesario hacerlo una vez, si corres nuevamente los comando no es necesario que vuelvas a cargar la instalación.
Definimos el directorio de trabajo
setwd("~")
Creamos dos carpetas, una donde guarderemos los datos generados y otra en donde guardaremos los gráficos.
path.Data = "./Results_Data"
if (!dir.exists(path.Data)) {dir.create(path.Data)}
path.plots = "./Results_plots"
if (!dir.exists(path.plots)) {dir.create(path.plots)}
Cargamos las bibliotecas que vamos a utilizar:
####
library(tximport)
library(DESeq2)
###
tximport: Importa la abundancia a nivel de transcrito, los recuentos estimados y las longitudes de los transcritos, y los resume en matrices para su uso con paquetes de análisis a nivel de gen posteriores. Podemos consultar la ayuda
help(tximport)
#txi <- tximport(files,
# type = c("none", "salmon", "sailfish", "alevin", "piscem", "oarfish", "kallisto",
"rsem", "stringtie"),
# tx2gene = tx2gene,
# ignoreTxVersion = T,
# dropInfReps=TRUE)
samples <- read.table("./datos.taller/mis_muestras.tsv",sep="\t",header=F)
samples
### Para tener mayor control vamos a ponerle nombre a las columnas
colnames(samples) <- c("Muestra","Condicion","Archivo")
samples
El argumentos sólo necesita la ruta de los archivos, por lo que seleccionando sólo la columna 1
files <- as.vector(samples$Archivo)
## Asociamos la ruta con la muestra, información en la columna 2
names(files) <- samples$Muestra
files
refChr22 <- read.table("./datos.taller/geneId_transcriptId_geneName_chr22.txt", sep="\t", header=F)
### Asociamos el nombre a las columnas
colnames(refChr22) <- c("gene_id","transcript_id","gene_name")
Sólo requerimos de las columnas "transcript_id","gene_id" de acuerdo a tximport, creamos una nueva tabla
tx2gene <- refChr22[,c("transcript_id","gene_id")]
head(tx2gene)
Ejecutamos tximport, es importante que tengamos los objetos files y tx2gene
txi <- tximport(files,
type = "kallisto",
tx2gene = tx2gene,
ignoreTxVersion = T,
dropInfReps=TRUE)
str(txi)
head(txi$counts)
head(txi$abundance)
Creamos matriz de expresión normalizada(TPM)
table.out <- txi$abundance
head(table.out)
### Dimenciones del objeto table.out
dim(table.out)
Incluimos referencia de los nombre de los genes.
geneId_geneName <- unique(refChr22[,-2])
table.out.names <- merge(geneId_geneName,table.out,by.x='gene_id',by.y=0)
dim(table.out.names)
head(table.out.names)
### Guardamos la tabla asociada a los nombres
write.table(table.out.names,
file=paste0(path.Data,"/exprTable.tsv"), sep="\t",
quote=F,
col.names=T,
row.names=F)
💡 NOTA
TPM (Transcripts per Millions)
- Divide los recuentos de lecturas por la longitud de cada gen en kilobases. Esto te da lecturas por kilobase (RPK).
- Suma todos los valores de RPK en una muestra y divide este número por 1,000,000. Este es tu factor de escalado "por millón".
- Divide los valores de RPK por el factor de escalado "por millón". Esto te da TPM.
### Objeto para estructurar los datos y hacer el DGEA
?DESeqDataSetFromTximport
# DESeqDataSetFromTximport(txi, colData, design, ...)
El objeto txi ya lo tenemos, sólo falta considerar las condiciones.
## Condición
coldata <- data.frame(condition = samples$Condicion)
coldata$condition <- factor(coldata$condition)
## Nombre de filas
rownames(coldata) <- samples$Muestra
head(coldata)
## Expresión diferencial
dds <- DESeqDataSetFromTximport(txi, coldata, ~condition)
dds <- DESeq(dds)
resultsNames(dds)
### Objeto donde se encuentra información de análisis de expresión
res <- results(dds)
head(res)
plotMA(res)
## salvar el resultado de
saveRDS(res, paste0(path.Data,"/res_dseq2.rds"))
cts <- counts(dds, normalized=T)
head(cts)
cts['ENSG00000008735',]
x.HBR <-cts['ENSG00000008735',1:3]
x.HBR
mh <- mean(x.HBR)
mh
x.UHR<-cts['ENSG00000008735',4:6]
x.UHR
mu <- mean(x.UHR)
mu
h <- log2(mh)
h
u <- log2(mu)
u
lfc_u_h <- u - h
lfc_u_h
log2(mu/mh)
res['ENSG00000008735',]
degs<-subset(res, (!is.na(res$padj) &
res$pvalue<0.05 &
baseMean>=50 & res$padj < 0.05 &
abs(res$log2FoldChange)>1))
Vamos a extraer sólo los 10 genes con menor p_value
top <- degs[order(degs$pvalue),]
myTpm <- subset(table.out, rownames(table.out) %in% rownames(top[1:10,]) )
dim(myTpm)
log2mat <- log2(myTpm)
Hacemos el heatmap
library (pheatmap)
my_hmap <- pheatmap(log2mat,
main="DEGs UHR vs HBR",
filename= paste0(path.plots,"/heatmap_top10.png"))
cambiamor el nombre de los genes para mejor interpretación
myTpm <- subset(table.out.names, table.out.names$gene_id %in% rownames(top[1:10,]))
dim(myTpm)
head(myTpm)
mat <- myTpm[,-c(1:2)]
rownames(mat) <- myTpm$gene_name
log2mat <- log2(mat)
my_hmap <- pheatmap(log2mat,
main="DEGs UHR vs HBR")
Si queremos utilizar todos los genes diferencialmente expresados
myTpm <- subset(table.out.names, table.out.names$gene_id %in% rownames(top[,]))
dim(myTpm)
head(myTpm)
mat <- myTpm[,-c(1:2)] + 1 ### Quitar ceros
rownames(mat) <- myTpm$gene_name
log2mat <- log2(mat)
my_hmap <- pheatmap(log2mat,
main="DEGs UHR vs HBR",
filename= paste0(path.plots,"/heatmap_all.png"),
height = 10)
💡
No es tan clara la diferencia, probemos en la versión normalizada.
###
my_hmap <- pheatmap(log2mat,
main="DEGs UHR vs HBR",
scale = "row",
filename= paste0(path.plots,"/heatmap_all_scaled.png"),
height = 10)
dev.off()
Un "volcano plot" es una técnica de visualización utilizada en la bioinformática y en otras ciencias biológicas para identificar cambios significativos en grandes conjuntos de datos, como en estudios de expresión génica o proteómica.
Los puntos que están alejados del origen en ambas direcciones (tanto en términos de significancia como en términos de magnitud del cambio) son los que suelen ser de mayor interés biológico.
library(EnhancedVolcano)
library(ggplot2)
### Tabla de los resultados
degs.frame = as.data.frame(res)
### Le incluimos el símbolo del gen
degs.frame.1 = merge(geneId_geneName,degs.frame,by.x='gene_id',by.y=0)
### Vemos que columnas podemos graficar
colnames(degs.frame.1)
#[1] "gene_id" "gene_name" "baseMean" "log2FoldChange"
# "lfcSE" "stat" "pvalue" "padj"
p1 <- EnhancedVolcano(degs.frame.1[,c("gene_name", "log2FoldChange", "padj")],
lab = degs.frame.1[,c("gene_name")],
x = 'log2FoldChange',
y = 'padj',
pCutoff = 0.05,
title = "UHR vs HBR")
p1
## Guardamos el gráfico
ggsave(paste0(path.plots,"/Volcano.png"))
De acuerdo a la teoría, existen diversos tipos de enriquecimiento de genes nos centraremos en dos:
- ORA
- GSEA
Técnica utilizada en bioinformática para identificar categorías funcionales, rutas metabólicas, o grupos de genes que están sobrerrepresentados en un conjunto de genes de interés. Este método se usa comúnmente para interpretar resultados de experimentos de expresión génica, como microarrays o secuenciación de RNA (RNA-seq).
Se implementará mediante el uso de EnrichR. EnrichR es un programa que te permite consultar múltiples bases de datos a la vez donde puedes ver que vías de señalización o rutas metabólicas están sobrerepresentadas o enriquecidas en un conjunto de genes en particular.
https://maayanlab.cloud/Enrichr/
EnrichR no se puede descargar, es un programa que tiene sólo existe en su propio sitio web, pero existe un paquete de R que nos permite conectarnos a la página web de EnrichR y ejecutarlo desde nuestra computadora.
https://cran.r-project.org/web/packages/enrichR/vignettes/enrichR.html
# cargamos el paquete en nuestra sesión
library(enrichR)
### Verificamos que tengamos conexión con el servidor
websiteLive <- getOption("enrichR.live")
#Welcome to enrichR
#Checking connection ...
#Enrichr ... Connection is Live!**
#FlyEnrichr ... Connection is Live!
#WormEnrichr ... Connection is Live!
#YeastEnrichr ... Connection is Live!
#FishEnrichr ... Connection is Live!
#OxEnrichr ... Connection is Live!
### seleccionamos sólo los datos para humano
if (websiteLive) {
listEnrichrSites()
setEnrichrSite("Enrichr") # Human genes
}
dbs <- listEnrichrDbs()
Veamos cuáles están actualizadas a 2023
grep("2023",dbs$libraryName,value=T)
Seleccionamos un par de bases de datos para nuestro ejercicio
misDBS <- c("GO_Biological_Process_2023","WikiPathway_2023_Human")
Vamos a hacer una prueba con unos genes de ejemplo
if (websiteLive) {
enriched <- enrichr(c("Runx1", "Gfi1", "Gfi1b", "Spi1", "Gata1", "Kdr"), misDBS)
}
Para ver los resultados, podemos checar individualmente los resultados de cada base de datos:
if (websiteLive) head(enriched[["GO_Biological_Process_2023"]])
if (websiteLive) head(enriched[["WikiPathway_2023_Human"]])
plotEnrich(enriched[[2]], showTerms = 20, numChar = 40, y = "Count", orderBy = "P.value")
### Si quieren salvar el gráfico
#ggsave(paste0(path.plots,"/ORA.png"))
¿Cómo generarías el otro gráfico para la otra base de datos?
Para guardar nuestra tabla de resultados
write.table(enriched[["WikiPathway_2023_Human"]],
file=paste0(path.Data,"/enriched_WikiPathways_2023.tsv"), sep="\t",
quote=F,
col.names=T,
row.names=F)
Técnica estadística utilizada para determinar si un conjunto predefinido de genes muestra diferencias significativas en sus niveles de expresión entre dos condiciones biológicas (por ejemplo, muestras tratadas vs. no tratadas). A diferencia de ORA (Over-Representation Analysis), que se enfoca en categorías de genes que están sobrerrepresentadas en un subconjunto de genes significativamente expresados, GSEA analiza todos los genes de un experimento de expresión génica para identificar patrones globales de expresión.
library(clusterProfiler)
library(enrichplot)
library(ggplot2)
library("org.Hs.eg.db", character.only = TRUE)
original_gene_list <- res$log2FoldChange
En caso que cerraste sesión, no es necesario correr el análsiis de expresión diferencial
## línea 203 guardamos el objeto
res <- readRDS("./Results_Data/res_dseq2.rds")
original_gene_list <- res$log2FoldChange
# Nombramos el vector
names(original_gene_list) <- rownames(res)
# 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)
head(gene_list)
?gseGO
- keyType 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", ##"BP"
keyType = "ENSEMBL",
minGSSize = 3,
maxGSSize = 800,
pvalueCutoff = 0.05,
verbose = TRUE,
OrgDb = "org.Hs.eg.db",
pAdjustMethod = "BH")
Utilidad
require(DOSE)
dotplot(gse, showCategory=10, split=".sign") + facet_grid(.~.sign)
geneset = 1
gseaplot(gse, by = "all", title = gse$Description[geneset], geneSetID = geneset)
goplot(gse)
###barplot
dat = data.frame("NES" = gse@result$enrichmentScore,
"p_value" = gse@result$p.adjust,
"geneset" = gse@result$Description)
ggplot(dat, aes(x=geneset, y=NES, fill=p_value)) +
geom_bar(stat="identity")+theme_minimal()+coord_flip()+
scale_fill_gradient(low="red",high="blue")
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 res2 en cual solo contiene los genes que hicieron match usando ña función bitr
res2 <- res[rownames(res) %in% dedup_ids$ENSEMBL,]
# Creamos una nueva coñumna en degs2 con los correspondientes ENTREZ IDs
res2$Y <- dedup_ids$ENTREZID
# Creamos un vector con el universo de genes
kegg_gene_list <- res2$log2FoldChange
# Nombramos el vector con los ENTREZ ids
names(kegg_gene_list) <- res2$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)
kk2 <- gseKEGG(geneList = kegg_gene_list,
organism = "hsa",
minGSSize = 3,
maxGSSize = 800,
pvalueCutoff = 0.05,
pAdjustMethod = "none",
keyType = "ncbi-geneid")
dotplot(kk2, showCategory = 10, title = "Enriched Pathways" , split=".sign") + facet_grid(.~.sign)
dat.kk2 = data.frame("NES" = kk2@result$enrichmentScore,
"p_value" = kk2@result$p.adjust,
"geneset" = kk2@result$Description)
ggplot(dat.kk2, aes(x=geneset, y=NES, fill=p_value)) +
geom_bar(stat="identity")+theme_minimal()+coord_flip()+
scale_fill_gradient(low="red",high="blue")
gseaplot(kk2, by = "all", title = kk2$Description[geneset], geneSetID = geneset)