Я хочу использовать параллельную функциональность пакета plyr
внутри функций.Параллельный * слой внутри функций
я бы подумал, что правильный способ экспортировать объекты, которые были созданы в теле функции (в данном примере, объект df_2
) выглядит следующим образом
# rm(list=ls())
library(plyr)
library(doParallel)
workers=makeCluster(2)
registerDoParallel(workers,core=2)
plyr_test=function() {
df_1=data.frame(type=c("a","b"),x=1:2)
df_2=data.frame(type=c("a","b"),x=3:4)
#export df_2 via .paropts
ddply(df_1,"type",.parallel=TRUE,.paropts=list(.export="df_2"),.fun=function(y) {
merge(y,df_2,all=FALSE,by="type")
})
}
plyr_test()
stopCluster(workers)
Однако, это бросает ошибка
Error in e$fun(obj, substitute(ex), parent.frame(), e$data) :
unable to find variable "df_2"
Так что я сделал некоторые исследования и выяснили, что она работает, если я экспортировать df_2
вручную
workers=makeCluster(2)
registerDoParallel(workers,core=2)
plyr_test_2=function() {
df_1=data.frame(type=c("a","b"),x=1:2)
df_2=data.frame(type=c("a","b"),x=3:4)
#manually export df_2
clusterExport(cl=workers,varlist=list("df_2"),envir=environment())
ddply(df_1,"type",.parallel=TRUE,.fun=function(y) {
merge(y,df_2,all=FALSE,by="type")
})
}
plyr_test_2()
stopCluster(workers)
Это дает правильный результат
type x.x x.y
1 a 1 3
2 b 2 4
Но я также узнал, что следующий код работает
workers=makeCluster(2)
registerDoParallel(workers,core=2)
plyr_test_3=function() {
df_1=data.frame(type=c("a","b"),x=1:2)
df_2=data.frame(type=c("a","b"),x=3:4)
#no export at all!
ddply(df_1,"type",.parallel=TRUE,.fun=function(y) {
merge(y,df_2,all=FALSE,by="type")
})
}
plyr_test_3()
stopCluster(workers)
plyr_test_3()
также дает правильный результат, и я не понимаю, почему. Я бы подумал, что мне нужно экспортировать df_2
...
Мой вопрос: как правильно обращаться с параллельными *ply
внутри функций? Очевидно, что plyr_test()
неверен. Я как-то чувствую, что ручной экспорт в plyr_test_2()
бесполезен. Но я также думаю, что plyr_test_3()
- это своего рода плохой стиль кодирования. Может кто-нибудь прокомментировать это? Спасибо, парни!
Как примечание: поскольку вы используете 'ddply', вы также можете попробовать использовать ** dplyr **, которая является следующей версией ** plyr ** для фреймов данных, и это может ускорить работу вашего кода больше, чем распараллеливание 'ddply'. См. [Введение в dplyr] (http://cran.rstudio.com/web/packages/dplyr/vignettes/introduction.html) –
Спасибо. Не знал об этом. – cryo111
И еще одно примечание для будущих вопросов: не ставьте 'rm (list = ls())' uncommented в ваш вопрос. Другие могут запускать код, не замечая его и тем самым удаляя важные данные из своих сеансов. –