2011-06-09 10 views
1

Est-il un moyen rapide et intelligent qui, disons de DF comme cegrands cadres de sous-ensembles de données

vec <- data.frame(Names = c("var1","var2","var3","var4","var5","var6","var7", 
          "var8","var9","var10","var11","var12","var13", 
          "var14") , 
        phase1= runif(14), 
        phase1.away= runif(14), 
        phase1_in= runif(14), 
        phase1_out= runif(14), 
        phase1.1= runif(14), 
        phase1.away.1= runif(14), 
        phase1_in.1= runif(14), 
        phase1_out.1= runif(14), 
        phase1.2= runif(14), 
        phase1.away.2= runif(14), 
        phase1_in.2= runif(14), 
        phase1_out.2= runif(14)) 

donner un nouveau DF comme ceci:

-allways commande selon phase1.x, donner les noms des variables correspondant aux valeurs, les valeurs de phase1_in et de phase1_out mais pas de phase1.away.

Ce que je fais est tout simplement

vec.o<-vec[with(vec, order(-phase1)),] 
d1<-vec.o[c("Names","phase1","phase1_in","phase1_out")] 

vec.o<-vec[with(vec, order(-phase1.1)),] 
d2<-vec.o[c("Names","phase1.1","phase1_in.1","phase1_out.1")] 

cbind(d1,d2) 

qui est extrêmement ennuyeux et je suis aussi sûr contre R-ish. Des idées intelligentes? J'ai affaire à de grandes trames de données en permanence et R semble être un peu lourd. Y a-t-il de bonnes publications à recommander à ces fins? (charge de nombreuses variables, créer des noms pour les opérations avec ces variables, etc ...,)

Répondre

3

EDIT: correction pour le phase.x de cas va à 10 et plus.

Je présume que vous avez beaucoup plus de phase1.1, phase1.2, donc une solution générale utilisant des expressions régulières serait quelque chose le long des lignes de:

# Make an id vector for the phase1.x, and give Names id -1 
# gives a warning as character is transformed to NA 
id <- as.numeric(gsub(".*\\.(\\d+$)","\\1",names(vec))) 
id[1] <- -1 
id[is.na(id)] <- 0 # first occurence, no .x 


veclist <- lapply(unique(id)[-1],function(i){ 
    #select all variables necessary, exclude the away 
    out <- vec[id %in% c(i,-1) & !grepl("away",names(vec))] 
    # find the phase1.x for ordering 
    ovec <- grepl("phase1(\\.\\d+)?$",names(out)) 
    # order and produce 
    out[order(out[,ovec]),] 
}) 

do.call(cbind,veclist) 

Il est basé sur la reconnaissance des le dernier nombre précédé d'un point, et coupe cela. S'il n'y a pas de dernier nombre précédé d'un point, c'est soit la variable Noms (que j'indique avec -1), soit la première phase (que j'indique avec 0).

Maintenant, vous avez un vecteur d'identification qui peut facilement sélectionner les variables qui appartiennent ensemble, de sorte que vous pouvez faire une boucle sur les valeurs uniques de id, sauf le premier (étant -1). En utilisant à nouveau les expressions régulières, vous pouvez obtenir la variable que vous voulez pour la construction d'une nouvelle base de données. Le do.call à la fin combine à nouveau toutes ces données.

Btw, Commander des sous-données va beaucoup plus vite que de commander la base de données d'origine, puis de sélectionner vos variables. C'est le gain que vous avez dans la solution de nullglob.

+0

Nice, bien qu'il semble que le nom de phase.x soit phase.10 ou supérieur, ID produit des zéros – Alex

+0

@Alex: belle prise. J'ai corrigé pour inclure phase.x va plus haut que 10. –

1

Ce n'est pas particulièrement intelligent, mais il est deux fois plus rapide (d'après mon simple indice de référence):

o1 <- order(-vec$phase1) 
o2 <- order(-vec$phase1.1) 
cbind(vec[o1,c("Names","phase1","phase1_in","phase1_out")], 
     vec[o2,c("Names","phase1.1","phase1_in.1","phase1_out.1")]) 

l'indice de référence est ici:

> n <- 2e5 
> vec<-data.frame(Names = as.character(runif(n)) , 
+     phase1= runif(n), 
+     phase1.away= runif(n), 
+     phase1_in= runif(n), 
+     phase1_out= runif(n), 
+     phase1.1= runif(n), 
+     phase1.away.1= runif(n), 
+     phase1_in.1= runif(n), 
+     phase1_out.1= runif(n), 
+     phase1.2= runif(n), 
+     phase1.away.2= runif(n), 
+     phase1_in.2= runif(n), 
+     phase1_out.2= runif(n)) 
> 
> 
> test1 <- function(){ 
+ vec.o<-vec[with(vec, order(-phase1)),] 
+ d1<-vec.o[c("Names","phase1","phase1_in","phase1_out")] 
+ vec.o<-vec[with(vec, order(-phase1.1)),] 
+ d2<-vec.o[c("Names","phase1.1","phase1_in.1","phase1_out.1")] 
+ d3 <- cbind(d1,d2) 
+ } 
> system.time(test1()) 
    user system elapsed 
    1.764 0.048 1.811 
> 
> 
> test2 <- function(){ 
+ o1 <- order(-vec$phase1) 
+ o2 <- order(-vec$phase1.1) 
+ d4 <- cbind(vec[o1,c("Names","phase1","phase1_in","phase1_out")], 
+    vec[o2,c("Names","phase1.1","phase1_in.1","phase1_out.1")]) 
+ } 
> system.time(test2()) 
    user system elapsed 
    0.736 0.056 0.791 
+0

Merci, mais j'ai la trame de données de 260 phases et c'est ce qui me préoccupe le plus puisque je voudrais éviter de le taper manuellement – Alex

+0

Vous n'avez pas besoin d'utiliser les noms de colonne pour sélectionner les colonnes; vous pourriez utiliser des index de colonne à la place, ce qui pourrait être plus rapide et plus facile. – nullglob

Questions connexes