R параллельные преобразования больших фреймов данных

По сути, у меня есть большой фрейм данных: 10 000 000x900 (строки, столбцы), и я пытаюсь параллельно преобразовать класс каждого столбца. Конечным результатом должен быть data.frame

Вот что у меня есть:

Представьте, что df - это уже определенный фрейм данных, все столбцы представляют собой смесь числовых и символьных классов.

library(snow) 
cl=makeCluster(50,type="SOCK")
cl.out=clusterApplyLB(cl,df,function(x)factor(x,exclude=NULL))

cl.out - это список того, что я хочу, за исключением того, что мне нужно, чтобы это было как класс data.frame

Итак, вот где я застрял... я пытаюсь объединить все элементы cl.out в data.frame, который не будет параллельным? (МЕДЛЕННО, время - проблема)

Могу ли я реализовать что-то еще с другим пакетом? (для каждого?)

Должен ли я жестко кодировать некоторые c, чтобы сделать это эффективно?

Любая помощь будет оценена по достоинству.

Спасибо,


person Kyle B    schedule 18.04.2013    source источник


Ответы (3)


Одна полезная парадигма состоит в том, чтобы подмножить и заменить все столбцы, рассматривая df как список.

df[] <- lapply(df, factor, exclude=NULL)

У вас действительно есть 50 ядер на одной машине, как следует из вашего вызова makeCluster? Если вы работаете не на компьютере с Windows, используйте вместо него пакет parallel и mclapply.

library(parallel)
options(mc.cores=50)
df[] <- mclapply(df, factor, exclude=NULL)

Это действительно поможет вам в вашей общей оценке? Кажется, что распространение и извлечение данных стоит столько же, сколько и расчеты.

> f = factor(rep("M", 10000000), levels=LETTERS)
> df = data.frame(f, f, f, f, f, f, f, f)
> system.time(lapply(df, factor, exclude=NULL))
   user  system elapsed 
  2.676   0.564   3.250 
> system.time(clusterApply(cl, df, factor, exclude=NULL))
   user  system elapsed 
  1.488   0.752   2.476 
> system.time(mclapply(df, factor, exclude=NULL))
   user  system elapsed 
  1.876   1.832   1.814 

(многоядерные и многопроцессорные тайминги, вероятно, сильно различаются).

person Martin Morgan    schedule 19.04.2013

Если у вас есть data.frame такого размера, я думаю, вы столкнетесь с проблемами памяти очень быстро.

Я думаю, что это будет намного быстрее и эффективнее.

Вы можете использовать set

library(data.table)

# to set as a data.table without having to copy 
setattr(df, 'class', c('data.table','data.frame')
alloc.col(df)

for(nn in names(df)){
   set(df, j = nn, value = factor(df[[nn]])
 }

Стоит прочитать data.table и параллельные вычисления

person mnel    schedule 19.04.2013

Поскольку data.frame — это список с атрибутом class, вы можете просто преобразовать список в data.frame с as.data.frame.

cl.out <- as.data.frame(cl.out)

Я заметил, что имена столбцов потеряны: если вы уверены, что они в том же порядке, вы можете установить их обратно с помощью:

names(cl.out) <- names(df)
person Vincent Zoonekynd    schedule 18.04.2013
comment
Преобразование с использованием этого процесса происходит довольно медленно. Я считаю, что под капотом происходит нечто большее, чем просто добавление атрибута класса в блок данных. - person Kyle B; 19.04.2013
comment
Это не очень чисто, но вы можете попробовать изменить атрибут напрямую: class(cl.out) <- "data.frame". - person Vincent Zoonekynd; 19.04.2013