idata.frame: Pourquoi erreur « is.data.frame (df) n'est pas vrai »?
-
09-10-2019 - |
Question
Je travaille avec une grande trame de données appelée exp ( ici ) 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.
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, peut-être mes données. J'ai donc essayé le jeu de données baseball
. L'exemple de idata.frame
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 mon travail par exemple?
ETA:
J'ai essayé aussi:
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 que je comprends comment utiliser idata.frame du tout.
La solution
Étant donné que vous travaillez avec des données « grands » et la recherche de perfomance, cela semble un ajustement parfait pour data.table
.
Plus précisément les arguments de lapply(.SD,FUN)
et .SDcols
avec by
Configuration du data.table
library(data.table)
DT <- as.data.table(exp)
iexp <- idata.frame(exp)
Les colonnes qui 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 évaluation 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
Autres conseils
Comportement étrange, mais même dans les docs, il dit que idata.frame est expérimentale. Vous avez probablement trouvé un bug. Peut-être que vous pouvez réécrire le chèque en haut de ddply que les tests is.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 peut être préférable de configurer un chron pour exécuter ce et stocker les résultats, quel que soit par jour / horaire.