Я работал над этим сегодня для data.frame (на самом деле data.table) с миллионами наблюдений и 35 столбцами. Моя цель состояла в том, чтобы вернуть список data.frames (data.tables), каждый с одной строкой. То есть я хотел разделить каждую строку на отдельный data.frame и сохранить их в списке.
Вот два метода, которые я придумал, которые были примерно в 3 раза быстрее, чем split(dat, seq_len(nrow(dat)))
для этого набора данных. Ниже я сравниваю эти три метода с набором данных из 7500 строк и 5 столбцов ( диафрагма повторяется 50 раз).
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
)
Это возвращает
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
Хотя различия не так велики, как в моем предыдущем тесте, прямой setDF
метод значительно быстрее на всех уровнях распределения прогонов с max (setDF) <min (split), а attr
метод обычно более чем в два раза быстрее.
Четвертый метод - это крайний чемпион, который представляет собой простой вложенный lapply
, возвращающий вложенный список. Этот метод иллюстрирует стоимость создания data.frame из списка. Более того, все методы, которые я пробовал с этой data.frame
функцией, были примерно на порядок медленнее, чем data.table
методы.
данные
dat <- vector("list", 50)
for(i in 1:50) dat[[i]] <- iris
dat <- setDF(rbindlist(dat))
split
каждого элементаdata.frame with 1 rows and N columns
вместоlist of length N