2010-10-20 17 views
4

Je travaille avec un grand cadre de données appelé exp (file here) dans R. Dans l'intérêt de la performance, il a été suggéré que je vérifie la fonction idata.frame() de plyr. Mais je pense que je l'utilise mal.idata.frame: Pourquoi l'erreur "is.data.frame (df) n'est pas VRAI"?

Mon appel initial, lent mais cela fonctionne:

df.median<-ddply(exp, 
       .(groupname,starttime,fPhase,fCycle), 
       numcolwise(median), 
       na.rm=TRUE) 

Avec idata.frame, Error: is.data.frame(df) is not TRUE

library(plyr) 
df.median<-ddply(idata.frame(exp), 
       .(groupname,starttime,fPhase,fCycle), 
       numcolwise(median), 
       na.rm=TRUE) 

Alors, je pensais que, peut-être mes données. J'ai donc essayé le jeu de données baseball. Le idata.frame exemple fonctionne très bien: dlply(idata.frame(baseball), "id", nrow) Mais si j'essaie quelque chose de similaire à mon appel désiré à l'aide baseball, il ne fonctionne pas:

bb.median<-ddply(idata.frame(baseball), 
       .(id,year,team), 
       numcolwise(median), 
       na.rm=TRUE) 
>Error: is.data.frame(df) is not TRUE 

Peut-être mon erreur dans la façon dont je précise les groupes? Quelqu'un sait comment faire fonctionner mon exemple?

ETA:

J'ai aussi essayé:

groupVars <- c("groupname","starttime","fPhase","fCycle") 
voi<-c('inadist','smldist','lardist') 

i<-idata.frame(exp) 
ag.median <- aggregate(i[,voi], i[,groupVars], median) 
Error in i[, voi] : object of type 'environment' is not subsettable 

qui utilise un moyen plus rapide d'obtenir les terre-pleins, mais donne une autre erreur. Je ne pense pas comprendre comment utiliser idata.frame.

+0

Oui, 'idata.frame' est encore expérimental donc il est préférable de travailler directement avec lui plutôt que d'utiliser les fonctions de résumé comme' colwise' – hadley

+0

Étant donné que vous recherchez des performances avec des données volumineuses, je passerais du temps à regarder au paquet 'data.table' – mnel

Répondre

1

Étant donné que vous travaillez avec de «grandes» données et que vous recherchez de la performance, cela semble convenir parfaitement à data.table.

Plus précisément, les lapply(.SD,FUN) et .SDcols arguments avec by

Configuration des data.table

library(data.table) 
DT <- as.data.table(exp) 
iexp <- idata.frame(exp) 

Quelles colonnes sont numeric

numeric_columns <- names(which(unlist(lapply(DT, is.numeric)))) 



dt.median <- DT[, lapply(.SD, median), by = list(groupname, starttime, fPhase, 
    fCycle), .SDcols = numeric_columns] 

une analyse comparative

library(rbenchmark) 
benchmark(data.table = DT[, lapply(.SD, median), by = list(groupname, starttime, 
    fPhase, fCycle), .SDcols = numeric_columns], 
plyr = ddply(exp, .(groupname, starttime, fPhase, fCycle), numcolwise(median), na.rm = TRUE), 
idataframe = ddply(exp, .(groupname, starttime, fPhase, fCycle), function(x) data.frame(inadist = median(x$inadist), 
     smldist = median(x$smldist), lardist = median(x$lardist), inadur = median(x$inadur), 
     smldur = median(x$smldur), lardur = median(x$lardur), emptyct = median(x$emptyct), 
     entct = median(x$entct), inact = median(x$inact), smlct = median(x$smlct), 
     larct = median(x$larct), na.rm = TRUE)), 
aggregate = aggregate(exp[, numeric_columns], 
         exp[, c("groupname", "starttime", "fPhase", "fCycle")], 
       median), 
replications = 5) 

##   test replications elapsed relative user.self 
## 4 aggregate   5 5.42 1.789  5.30 
## 1 data.table   5 3.03 1.000  3.03  
## 3 idataframe   5 11.81 3.898  11.77  
## 2  plyr   5 9.47 3.125  9.45  
+0

Nice! Je peux inclure ceci dans le refactor suivant. – dnagirl

0

Comportement étrange, mais même dans les docs il est dit que idata.frame est expérimental. Vous avez probablement trouvé un bug. Peut-être que vous pourriez réécrire la vérification en haut de ddply que les tests sont.data.frame().

Dans tous les cas, cette coupe environ 20% du temps (sur mon système):

system.time(df.median<-ddply(exp, .(groupname,starttime,fPhase,fCycle), function(x) data.frame(
inadist=median(x$inadist), 
smldist=median(x$smldist), 
lardist=median(x$lardist), 
inadur=median(x$inadur), 
smldur=median(x$smldur), 
lardur=median(x$lardur), 
emptyct=median(x$emptyct), 
entct=median(x$entct), 
inact=median(x$inact), 
smlct=median(x$smlct), 
larct=median(x$larct), 
na.rm=TRUE)) 
) 

Shane vous a demandé dans un autre poste si vous pouviez mettre en cache les résultats de votre script. Je n'ai pas vraiment une idée de votre flux de travail, mais il est peut-être préférable de configurer une chronologie pour l'exécuter et stocker les résultats, tous les jours/toutes les heures.

+0

c'est intéressant que la spécification des colonnes accélère les choses (c'est aussi le cas sur mon système), mais jusqu'à présent, la solution la plus rapide est d'utiliser' aggregate() '.Quoi qu'il en soit, la raison pour laquelle j'ai utilisé mon ancien appel lent dans cette question était parce que cela provoquait l'idoke.frame() 'à s'étouffer. J'ai beaucoup d'appels qui utilisent le cadre de données exp, et je pensais que si je pouvais remplacer un idata.frame, il pourrait accélérer tous les appels de manière significative. – dnagirl

+0

Vous pouvez utiliser 'idata.frame' avec cet appel - mais cela ne vous donne qu'une augmentation de 10%, car vous ne faites pas autant de divisions. – hadley

+0

Et oui, 'aggregate' va actuellement battre' ddply' + 'colwise'. Penser à comment faire mieux pour la prochaine version. – hadley