Pracowałem nad tym dzisiaj dla ramki data.frame (tak naprawdę data.table) z milionami obserwacji i 35 kolumnami. Moim celem było zwrócenie listy data.frames (data.tables), każda z jednym wierszem. Oznacza to, że chciałem podzielić każdy wiersz na osobną ramkę data.frame i zapisać je na liście.
Oto dwie metody, które wymyśliłem, które były około 3 razy szybsze niż w split(dat, seq_len(nrow(dat)))
przypadku tego zestawu danych. Poniżej porównuję te trzy metody na zestawie danych z 7500 wierszami i 5 kolumnami ( tęczówka powtórzona 50 razy).
library(data.table)
library(microbenchmark)
microbenchmark(
split={dat1 <- split(dat, seq_len(nrow(dat)))},
setDF={dat2 <- lapply(seq_len(nrow(dat)),
function(i) setDF(lapply(dat, "[", i)))},
attrDT={dat3 <- lapply(seq_len(nrow(dat)),
function(i) {
tmp <- lapply(dat, "[", i)
attr(tmp, "class") <- c("data.table", "data.frame")
setDF(tmp)
})},
datList = {datL <- lapply(seq_len(nrow(dat)),
function(i) lapply(dat, "[", i))},
times=20
)
To wraca
Unit: milliseconds
expr min lq mean median uq max neval
split 861.8126 889.1849 973.5294 943.2288 1041.7206 1250.6150 20
setDF 459.0577 466.3432 511.2656 482.1943 500.6958 750.6635 20
attrDT 399.1999 409.6316 461.6454 422.5436 490.5620 717.6355 20
datList 192.1175 201.9896 241.4726 208.4535 246.4299 411.2097 20
Chociaż różnice nie są tak duże jak w moim poprzednim teście, setDF
metoda prosta jest znacznie szybsza na wszystkich poziomach dystrybucji przebiegów z max (setDF) <min (split), a attr
metoda jest zwykle ponad dwukrotnie szybsza.
Czwartą metodą jest ekstremalny mistrz, który jest prostym zagnieżdżonym lapply
, zwracającym zagnieżdżoną listę. Ta metoda ilustruje koszt tworzenia ramki data.frame z listy. Co więcej, wszystkie metody, które wypróbowałem z tą data.frame
funkcją, były mniej więcej o rząd wielkości wolniejsze niż data.table
techniki.
dane
dat <- vector("list", 50)
for(i in 1:50) dat[[i]] <- iris
dat <- setDF(rbindlist(dat))
split
każdy element ma typdata.frame with 1 rows and N columns
zamiastlist of length N