Question

J'ai un data.frame nommé « d » de lignes et 1.300.000 ~ 4 colonnes et une autre data.frame nommée « gc » de lignes et 12.000 ~ 2 colonnes (mais voir l'exemple ci-dessous plus petit).

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") )

Voici comment ressemble à "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

Et voici "gc":

  gene chr
1    a  c1
2    b  c2
3    c  c3

Je veux ajouter une 5ème colonne « d » en incorporant des données de « gc » qui correspondent à la 1ère colonne de « d ». Pour le moment je suis en utilisant sapply .

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

Mais sur les données réelles, il faut un temps « très long » (je suis en cours d'exécution avec la commande « system.time () » depuis plus de 30 minutes et il est toujours pas fini).

Avez-vous une idée de la façon dont je pourrais réécrire cela d'une manière intelligente? Ou devrais-je envisager d'utiliser l'option plyr , peut-être avec le « parallèle » (j'ai quatre cœurs sur mon ordinateur)? Dans ce cas, quelle serait la meilleure syntaxe?

Merci à l'avance.

Était-ce utile?

La solution

Je pense que vous pouvez simplement utiliser le facteur comme indice:

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

fait la même chose 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

Mais est beaucoup plus rapide:

> 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 

Edit:

Pour développer un peu sur mon commentaire. La trame de données de gc exige une ligne pour chaque niveau de gene dans l'ordre des niveaux pour que cela fonctionne:

 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

Mais il est difficile de ne pas fixer que:

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

Autres conseils

Une solution alternative qui ne merge pas battu le calendrier sage approche de Sasha, mais il est plus généralisables et lisible, est simplement les deux trames de données:

d <- merge(d, gc)

J'ai un système plus lent, donc voici mes horaires:

> 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 

L'avantage est que vous pouvez avoir plusieurs clés, contrôle fin sur les éléments qui ne correspondent pas, etc.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top