R: преобразование каждой строки кадра данных в элемент списка
У меня есть ряд операций с кадрами данных, которые я хотел бы ускорить с помощью mclapply()
или других lapply()
подобных функций. Один из самых простых способов борьбы с этим - сделать каждую строку кадра данных небольшим фреймом данных в списке. Я могу сделать это довольно легко с помощью plyr
следующим образом:
df <- data.frame( a=rnorm(1e4), b=rnorm(1e4))
require(plyr)
system.time(myList <- alply( df, 1, function(x) data.frame(x) ))
Как только у меня есть данные в виде списка, я могу легко делать такие вещи, как:
mclapply( myList, function(x) doSomething(x$a) )
Это работает плавно, но у меня довольно много данных, а шаг adply()
довольно медленный. Я попытался использовать многоядерный параллельный бэкэнд на шаге adply
, но он никогда не использовал больше одного процессора, хотя я зарегистрировал 8. Я подозрительно, что параллельная опция может не работать с этим типом проблемы.
Любые советы о том, как сделать это быстрее? Может быть, базовое решение R?
Ответы
Ответ 1
Просто используйте split
. Это в несколько раз быстрее, чем ваша строка adply
.
> system.time(myList <- alply( df, 1, function(x) data.frame(x) ))
user system elapsed
7.53 0.00 7.57
> system.time( splitList <- split(df, 1:NROW(df)) )
user system elapsed
1.73 0.00 1.74
>
Я подозреваю, что параллельный бэкэнд на adply
предназначен только для оценки функции (не расщепления и повторного объединения).
UPDATE:
Если вы можете преобразовать ваш data.frame в матрицу, решение ниже будет быстрым. Вы можете использовать split
, но он будет отбрасывать имена и возвращать вектор в каждом элементе списка.
> m <- as.matrix(df)
> system.time( matrixList <- lapply(1:NROW(m), function(i) m[i,,drop=FALSE]) )
user system elapsed
0.02 0.00 0.02
> str(matrixList[[1]])
num [1, 1:2] -0.0956 -1.5887
- attr(*, "dimnames")=List of 2
..$ : NULL
..$ : chr [1:2] "a" "b"
> system.time( matrixSplitList <- split(m, 1:NROW(m)) )
user system elapsed
0.01 0.00 0.02
> str(matrixSplitList[[1]])
num [1:2] -0.0956 -1.5887
Ответ 2
Как насчет этого?
jdList <- split(df, 1:nrow(df))
> class(jdList[[1]])
[1] "data.frame"
> system.time(jdList <- split(df, 1:nrow(df)))
user system elapsed
1.67 0.02 1.70
> system.time(myList <- alply( df, 1, function(x) data.frame(x) ))
user system elapsed
7.2 0.0 7.3