Myślę, że używam niepoprawnie plyr. Czy ktoś mógłby mi powiedzieć, czy jest to "wydajny" kod plyr?Dlaczego plyr jest taki wolny?
require(plyr)
plyr <- function(dd) ddply(dd, .(price), summarise, ss=sum(volume))
Mały kontekst: Mam kilka dużych problemów z agregacją i zauważyłem, że każdy z nich poświęcił trochę czasu. Próbując rozwiązać te problemy, zainteresowałem się wydajnością różnych procedur agregacji w R.
Przetestowałem kilka metod agregacji - i zacząłem czekać cały dzień.
Kiedy w końcu otrzymałem wyniki, odkryłem ogromną lukę między metodą plyr a innymi - co sprawia, że myślę, że zrobiłem coś nie tak.
Pobiegłem następujący kod (myślałem, że sprawdzić nowy pakiet dataframe gdy byłem na nią):
require(plyr)
require(data.table)
require(dataframe)
require(rbenchmark)
require(xts)
plyr <- function(dd) ddply(dd, .(price), summarise, ss=sum(volume))
t.apply <- function(dd) unlist(tapply(dd$volume, dd$price, sum))
t.apply.x <- function(dd) unlist(tapply(dd[,2], dd[,1], sum))
l.apply <- function(dd) unlist(lapply(split(dd$volume, dd$price), sum))
l.apply.x <- function(dd) unlist(lapply(split(dd[,2], dd[,1]), sum))
b.y <- function(dd) unlist(by(dd$volume, dd$price, sum))
b.y.x <- function(dd) unlist(by(dd[,2], dd[,1], sum))
agg <- function(dd) aggregate(dd$volume, list(dd$price), sum)
agg.x <- function(dd) aggregate(dd[,2], list(dd[,1]), sum)
dtd <- function(dd) dd[, sum(volume), by=(price)]
obs <- c(5e1, 5e2, 5e3, 5e4, 5e5, 5e6, 5e6, 5e7, 5e8)
timS <- timeBasedSeq('20110101 083000/20120101 083000')
bmkRL <- list(NULL)
for (i in 1:5){
tt <- timS[1:obs[i]]
for (j in 1:8){
pxl <- seq(0.9, 1.1, by= (1.1 - 0.9)/floor(obs[i]/(11-j)))
px <- sample(pxl, length(tt), replace=TRUE)
vol <- rnorm(length(tt), 1000, 100)
d.df <- base::data.frame(time=tt, price=px, volume=vol)
d.dfp <- dataframe::data.frame(time=tt, price=px, volume=vol)
d.matrix <- as.matrix(d.df[,-1])
d.dt <- data.table(d.df)
listLabel <- paste('i=',i, 'j=',j)
bmkRL[[listLabel]] <- benchmark(plyr(d.df), plyr(d.dfp), t.apply(d.df),
t.apply(d.dfp), t.apply.x(d.matrix),
l.apply(d.df), l.apply(d.dfp), l.apply.x(d.matrix),
b.y(d.df), b.y(d.dfp), b.y.x(d.matrix), agg(d.df),
agg(d.dfp), agg.x(d.matrix), dtd(d.dt),
columns =c('test', 'elapsed', 'relative'),
replications = 10,
order = 'elapsed')
}
}
Badanie miało sprawdzić się do 5E8, ale zajęło zbyt długo - głównie z powodu plyr. Tabela 5e5 ostateczna pokazuje problem:
$`i= 5 j= 8`
test elapsed relative
15 dtd(d.dt) 4.156 1.000000
6 l.apply(d.df) 15.687 3.774543
7 l.apply(d.dfp) 16.066 3.865736
8 l.apply.x(d.matrix) 16.659 4.008422
4 t.apply(d.dfp) 21.387 5.146054
3 t.apply(d.df) 21.488 5.170356
5 t.apply.x(d.matrix) 22.014 5.296920
13 agg(d.dfp) 32.254 7.760828
14 agg.x(d.matrix) 32.435 7.804379
12 agg(d.df) 32.593 7.842397
10 b.y(d.dfp) 98.006 23.581809
11 b.y.x(d.matrix) 98.134 23.612608
9 b.y(d.df) 98.337 23.661453
1 plyr(d.df) 9384.135 2257.972810
2 plyr(d.dfp) 9384.448 2258.048123
Czy to prawda? Dlaczego plyr 2250x jest wolniejszy niż data.table
? Dlaczego zastosowanie nowego pakietu ramek danych nie miało znaczenia?
informacji sesja jest:
> sessionInfo()
R version 2.15.1 (2012-06-22)
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] xts_0.8-6 zoo_1.7-7 rbenchmark_0.3 dataframe_2.5 data.table_1.8.1 plyr_1.7.1
loaded via a namespace (and not attached):
[1] grid_2.15.1 lattice_0.20-6 tools_2.15.1
W przypadku stosunkowo prostych problemów manipulacji danymi/agregacji, znalazłem tabeli dane się niezwykle szybko. Jeśli może to zrobić, wcale nie jestem zaskoczony, że jest to oczywisty zwycięzca. Nie jestem wystarczająco zaznajomiony z 'plyr', aby go skomentować. – Joshua
Czy obejrzałeś dokumentację dla 'plyr' i' data.table'? Jeśli dobrze pamiętam, 'plyr' działa z base-'R'' data.frame's. 'data.table' używa zupełnie innej reprezentacji, używając kolumn z kluczami i wydajnego sortowania radik. W ten sposób jest znacznie więcej bazy danych. –
Mam spojrzenie - ale nie mogłem tego rozgryźć. plyr jest czymś więcej niż odrobinę wolniejszym ... zastosowanie rodziny, agresywności i przez to są bardzo szybkie - i są one podstawą. właśnie dlatego doszedłem do wniosku, że muszę popełnić jakiś błąd debiutanta z plyr. – ricardo