R: преобразование каждой строки фрейма данных в элемент списка - PullRequest
18 голосов
/ 25 февраля 2011

У меня есть ряд операций с фреймами данных, которые я хотел бы ускорить, используя 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. Я подозреваю, что параллельный вариант может не работать с такой проблемой

Какие-нибудь советы, как сделать это быстрее? Может быть решение Base R?

Ответы [ 2 ]

15 голосов
/ 25 февраля 2011

Просто используйте 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 предназначен только для оценки функции (не для разделения и повторного объединения).ОБНОВЛЕНИЕ:
Если вы можете преобразовать ваш 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
6 голосов
/ 25 февраля 2011

Как насчет этого?

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 
...