Pregunta Alternativas para los bucles en R?


Tengo 2 archivos que me gustaría combinar usando R.

head(bed)
chr8 41513235 41513282 ANK1.Exon1
chr8 41518973 41519092 ANK1.Exon2

El primero es dar intervalos y sus nombres. (Cromosoma, de, a, nombre)

head(coverage)
chr1 41513235 20
chr1 41513236 19
chr1 41513237 19

El segundo da coberturas para Bases individuales. (Cromosoma, posición, cobertura)

Ahora quiero obtener el nombre de cada Exón escrito al lado de cada Posición. Esto dará lugar a algunas posiciones sin "Exon" que quiero eliminar después.

Descubrí una manera de cómo hacer lo que quiero. Sin embargo, necesita 3 bucles for y alrededor de 15 horas de tiempo de cálculo. Dado que los bucles no son la mejor práctica en R, me gustaría saber si alguien conoce una manera mejor que:

coverage <- cbind(coverage, "Exon")
coverage[,4] <- NA

for(i in 1:nrow(bed)){
 for(n in bed[i,2]:bed[i,3]{
  for(m in 1:nrow(coverage)){
   if(coverage[m,2]==n){
    file[m,4] <- bed[i,4]
   }
  }
 }
}

na.omit(coverage)

Dado que las tres posiciones se encuentran en el intervalo "ANK1.Exon1", la salida debería tener este aspecto:

head(coverage) 
chr1 41513235 20 ANK1.Exon1 
chr1 41513236 19 ANK1.Exon1 
chr1 41513237 19 ANK1.Exon1 

5
2018-05-19 08:45


origen


Respuestas:


La forma más rápida de realizar lo que estaba buscando era:

library("sqldf")
res <- sqldf("select * from coverage f1 inner join bed f2
on(f1.position >=f2.'from' and f1.position <=f2.'to')")

El tiempo de cálculo se redujo a segundos. Para obtener el resultado exacto como se indicó anteriormente, el marco de datos se redujo aún más.

res <- cbind(res[1:4],res[8])

Gracias por toda tu ayuda.

Editar: para grandes conjuntos de datos donde las mismas posiciones pueden aparecer en más de un cromosoma, es útil agregar más:

res <- sqldf("select * from coverage f1 inner join bed f2
on(f1.position >=f2.'from' and f1.position <=f2.'to' and f1.Chromosome = f2.Chromosome)")

5
2018-05-19 10:26



este algoritmo es lineal, si bed y coverage las entradas se ordenan, y bed la entrada no es superposición de intevalos

> coverage <- read.table("coverage")
> bed <- read.table("bed")
> 
> coverage <- cbind(coverage, "Exon")
> coverage[,4] <- NA
> 
> i_coverage <- 1
> i_bed <- 1
> 
> while(i_coverage <= length(coverage[,1]) && i_bed <= length(bed[,1])) {
+   if(coverage[i_coverage, 2] < bed[i_bed, 2]){
+     i_coverage <- i_coverage + 1
+   }else{
+     #then coverage[i_coverage, 2] >= bed[i_bed, 2]
+     if(coverage[i_coverage, 2] <= bed[i_bed, 3]){
+       coverage[i_coverage,4] <- as.character(bed[i_bed, 4])
+       i_coverage <- i_coverage + 1
+     }else{
+       i_bed <- i_bed + 1
+     }
+   }
+ }

usted obtiene:

> print(coverage)
V1       V2 V3     "Exon"
1 chr1 41513235 20 ANK1.Exon1
2 chr1 41513236 19 ANK1.Exon1
3 chr1 41513237 19 ANK1.Exon1

2
2018-05-19 18:10



Usando GenomicRanges:

library("GenomicRanges")

#data
x1 <- read.table(text="chr1 41513235 41513282 ANK1.Exon1
chr1 41518973 41519092 ANK1.Exon2")

x2 <- read.table(text="chr1 41513235 20
chr1 41513236 19
chr1 41513237 19")

#Convert to Granges object:
g1 <-  GRanges(seqnames=x1$V1,
               IRanges(start=x1$V2,
                       end=x1$V3),
               Exon=x1$V4)


g2 <-  GRanges(seqnames=x2$V1,
               IRanges(start=x2$V2,
                       end=x2$V2),
               covN=x2$V3)
#merge
mergeByOverlaps(g1,g2)

#output
# DataFrame with 3 rows and 4 columns
#                            g1       Exon                          g2      covN
#                     <GRanges>   <factor>                   <GRanges> <integer>
# 1 chr1:*:[41513235, 41513282] ANK1.Exon1 chr1:*:[41513235, 41513235]        20
# 2 chr1:*:[41513235, 41513282] ANK1.Exon1 chr1:*:[41513236, 41513236]        19
# 3 chr1:*:[41513235, 41513282] ANK1.Exon1 chr1:*:[41513237, 41513237]        19

2
2018-05-19 21:14