Pregunta

Tengo un datos de datos llamado "D" de ~ 1,300,000 líneas y 4 columnas y otro Data.Frame llamado "GC" de ~ 12,000 líneas y 2 columnas (pero vea el ejemplo más pequeño a continuación).

d <- data.frame( gene=rep(c("a","b","c"),4), val=rnorm(12), ind=c( rep(rep("i1",3),2), rep(rep("i2",3),2) ), exp=c( rep("e1",3), rep("e2",3), rep("e1",3), rep("e2",3) ) )
gc <- data.frame( gene=c("a","b","c"), chr=c("c1","c2","c3") )

Así es como se ve "D":

   gene         val ind exp
1     a  1.38711902  i1  e1
2     b -0.25578496  i1  e1
3     c  0.49331256  i1  e1
4     a -1.38015272  i1  e2
5     b  1.46779219  i1  e2
6     c -0.84946320  i1  e2
7     a  0.01188061  i2  e1
8     b -0.13225808  i2  e1
9     c  0.16508404  i2  e1
10    a  0.70949804  i2  e2
11    b -0.64950167  i2  e2
12    c  0.12472479  i2  e2

Y aquí está "GC":

  gene chr
1    a  c1
2    b  c2
3    c  c3

Quiero agregar una quinta columna a "D" incorporando datos de "GC" que coincidan con la primera columna de "D". Por el momento que estoy usando zarza.

d$chr <- sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )

Pero en los datos reales, lleva un tiempo "muy largo" (estoy ejecutando el comando con "System.time ()" ya que más de 30 minutos y todavía no está terminado).

¿Tienes alguna idea de cómo podría reescribir esto de una manera inteligente? O debería considerar usar plyr, ¿tal vez con la opción "paralela" (tengo cuatro núcleos en mi computadora)? En tal caso, ¿cuál sería la mejor sintaxis?

Gracias por adelantado.

¿Fue útil?

Solución

Creo que puedes usar el factor como índice:

gc[ d[,1], 2]
 [1] c1 c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3
Levels: c1 c2 c3

hace lo mismo que:

 sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )
 [1] c1 c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3
Levels: c1 c2 c3

Pero es mucho más rápido:

> system.time(replicate(1000,sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )))
   user  system elapsed 
   5.03    0.00    5.02 
> 
> system.time(replicate(1000,gc[ d[,1], 2]))
   user  system elapsed 
   0.12    0.00    0.13 

Editar:

Para expandirse un poco en mi comentario. los gc DataFrame requiere una fila para cada nivel de gene En el orden de los niveles para que esto funcione:

 d <- data.frame( gene=rep(c("a","b","c"),4), val=rnorm(12), ind=c( rep(rep("i1",3),2), rep(rep("i2",3),2) ), exp=c( rep("e1",3), rep("e2",3), rep("e1",3), rep("e2",3) ) )
gc <- data.frame( gene=c("c","a","b"), chr=c("c1","c2","c3") )

gc[ d[,1], 2]
 [1] c1 c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3
Levels: c1 c2 c3

sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )
 [1] c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3 c1
Levels: c1 c2 c3

Pero no es difícil arreglar eso:

levels(gc$gene) <- levels(d$gene) # Seems redundant as this is done right quite often automatically
gc <- gc[order(gc$gene),]


gc[ d[,1], 2]
 [1] c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3 c1
Levels: c1 c2 c3

sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )
 [1] c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3 c1
Levels: c1 c2 c3

Otros consejos

Una solución alternativa que no supere el enfoque de Sasha en cuanto a tiempo, pero es más generalizable y legible, es simplemente para simplemente merge Los dos marcos de datos:

d <- merge(d, gc)

Tengo un sistema más lento, así que aquí están mis tiempos:

> system.time(replicate(1000,sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )))
   user  system elapsed 
  11.22    0.12   11.86 
> system.time(replicate(1000,gc[ d[,1], 2])) 
   user  system elapsed 
   0.34    0.00    0.35 
> system.time(replicate(1000, merge(d, gc, by="gene"))) 
   user  system elapsed 
   3.35    0.02    3.40 

El beneficio es que puede tener múltiples claves, control fino sobre elementos no coincidentes, etc.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top