Je travaillais là-dessus aujourd'hui pour un data.frame (vraiment un data.table) avec des millions d'observations et 35 colonnes. Mon objectif était de renvoyer une liste de data.frames (data.tables) chacun avec une seule ligne. Autrement dit, je voulais diviser chaque ligne en un data.frame séparé et les stocker dans une liste.
Voici deux méthodes que j'ai proposées qui étaient environ 3 fois plus rapides que split(dat, seq_len(nrow(dat)))
pour cet ensemble de données. Ci-dessous, je compare les trois méthodes sur un ensemble de données de 7500 lignes et 5 colonnes ( iris répété 50 fois).
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
)
Cela renvoie
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
Bien que les différences ne soient pas aussi importantes que dans mon test précédent, la setDF
méthode directe est nettement plus rapide à tous les niveaux de la distribution des exécutions avec max (setDF) <min (split) et la attr
méthode est généralement plus de deux fois plus rapide.
Une quatrième méthode est le champion extrême, qui est un simple imbriqué lapply
, renvoyant une liste imbriquée. Cette méthode illustre le coût de construction d'un data.frame à partir d'une liste. De plus, toutes les méthodes que j'ai essayées avec la data.frame
fonction étaient à peu près un ordre de grandeur plus lentes que les data.table
techniques.
Les données
dat <- vector("list", 50)
for(i in 1:50) dat[[i]] <- iris
dat <- setDF(rbindlist(dat))
split
chaque élément a un typedata.frame with 1 rows and N columns
au lieu delist of length N