Eu estava trabalhando nisso hoje para um data.frame (realmente um data.table) com milhões de observações e 35 colunas. Meu objetivo era retornar uma lista de data.frames (data.tables), cada uma com uma única linha. Ou seja, eu queria dividir cada linha em um data.frame separado e armazená-los em uma lista.
Aqui estão dois métodos que eu criei que eram aproximadamente três vezes mais rápidos do que split(dat, seq_len(nrow(dat)))
para esse conjunto de dados. Abaixo, comparo os três métodos em um conjunto de dados de 5 colunas e 7500 linhas, com 7500 linhas ( íris repetida 50 vezes).
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
)
Isso retorna
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
Embora as diferenças não sejam tão grandes quanto no meu teste anterior, o setDF
método direto é significativamente mais rápido em todos os níveis da distribuição de execuções com max (setDF) <min (split) e o attr
método geralmente é mais do que o dobro da velocidade.
Um quarto método é o campeão extremo, que é um simples aninhado lapply
, retornando uma lista aninhada. Este método exemplifica o custo de construção de um data.frame a partir de uma lista. Além disso, todos os métodos que tentei com a data.frame
função eram aproximadamente uma ordem de magnitude mais lenta que as data.table
técnicas.
dados
dat <- vector("list", 50)
for(i in 1:50) dat[[i]] <- iris
dat <- setDF(rbindlist(dat))
split
cada elemento, ele tem o tipo emdata.frame with 1 rows and N columns
vez de #list of length N