2017-06-21 31 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