2017-06-21 30 views
0

我有一個函數,我動態地建立多個公式作爲字符串,並將它們投射到公式爲as.formula。然後我使用doSNOWforeach以並行處理的方式調用該函數,並通過dplyr::mutate_使用這些公式。foreach包的範圍如何使用as.formula,SE dplyr和lapply時的環境?

當我使用lapply(formula_list, as.formula)時,在並行運行時出現錯誤could not find function *custom_function*,但在本地運行時工作正常。但是,當我使用lapply(formula_list, function(x) as.formula(x)時,它可以在並行和本地中使用。

爲什麼?什麼是正確的方式來了解這裏的環境和「正確」的方式來編碼?

我做得到,說一個警告:In e$fun(obj, substitute(ex), parent.frame(), e$data) : already exporting variable(s): *custom_func*

一個最小的可重複的例子如下。

# Packages 
library(dplyr) 
library(doParallel) 
library(doSNOW) 
library(foreach) 

# A simple custom function 
    custom_sum <- function(x){ 
    sum(x) 
    } 

# Functions that call create formulas and use them with nse dplyr: 
    dplyr_mut_lapply_reg <- function(df){ 
    my_dots <- setNames(
     object = lapply(list("~custom_sum(Sepal.Length)"), as.formula), 
     nm  = c("Sums") 
    ) 

    return(
     df %>% 
     group_by(Species) %>% 
     mutate_(.dots = my_dots) 
    ) 
    } 

    dplyr_mut_lapply_lambda <- function(df){ 
    my_dots <- setNames(
     object = lapply(list("~custom_sum(Sepal.Length)"), function(x) as.formula(x)), 
     nm  = c("Sums") 
    ) 

    return(
     df %>% 
     group_by(Species) %>% 
     mutate_(.dots = my_dots) 
    ) 
} 

#1. CALLING BOTH LOCALLY 
dplyr_mut_lapply_lambda(iris) #works 
dplyr_mut_lapply_reg(iris) #works 

#2. CALLING IN PARALLEL 
    #Faux Parallel Setup 
    cl <- makeCluster(1, outfile="") 
    registerDoSNOW(cl) 

    # Call Lambda Version WORKS 
    foreach(j = 1, 
      .packages = c("dplyr", "tidyr"), 
      .export = lsf.str() 
     ) %dopar% { 
    dplyr_mut_lapply_lambda(iris) 
    } 



    # Call Regular Version FAILS 
    foreach(j = 1, 
      .packages = c("dplyr", "tidyr"), 
      .export = lsf.str() 
     ) %dopar% { 
    dplyr_mut_lapply_reg(iris) 
    } 

    # Close Cluster 
    stopCluster(cl) 

編輯:我在原來的文章標題,我寫,我用NSE,但使用標準的評價我真正的意思。哎呦。我相應地改變了這一點。

回答

1

我沒有確切的答案,爲什麼在這裏,但future包(我是作者)處理這些類型的「棘手」全局變量 - 它們很棘手,因爲它們不是包的一部分,它們是嵌套的,即一個全局調用另一個全局。例如,如果您使用:

library("doFuture") 
cl <- parallel::makeCluster(1, outfile = "") 
plan(cluster, workers = cl) 
registerDoFuture() 

有問題的「Call Regular Version FAILS」情況現在應該起作用。現在

,上述使用parallel::makeCluster()默認爲type = "PSOCK",而如果您加載doSNOW你snow::makeCluster()默認爲type = "MPI"。不幸的是,爲未來的封裝完整MPI backend is yet not implemented。因此,如果你正在尋找一個MPI解決方案,那麼這對你還沒有幫助。

+0

這看起來超級有用!我一定會對此進行更多的調查,但我會把問題留給公衆,以便我更好地理解核心問題。 – bigfoot56