2017-06-21 5 views
0

私は動的に複数の数式を文字列として構築し、as.formulaの数式にキャストする関数を持っています。私はその後、doSNOWforeachを使ってその関数を並列プロセスで呼び出し、これらの式をdplyr::mutate_まで使っています。foreachパッケージのスコープR 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) 

はEDIT:私のオリジナルのポストのタイトルで、私はNSEを使用していたことを書いたが、私は本当に標準の評価を使用してのもの。うわー。私はそれに応じてこれを変更しました。

答えて

1

ここでなぜ正確な答えが得られませんが、futureパッケージ(私は作者です)がこれらのタイプの「トリッキーな」グローバルを処理します。パッケージに含まれていないために厄介ですつまり、1つのグローバルは別のグローバルを呼び出します。たとえば、次のように指定した場合:

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

「Call Regular Version FAILS」のケースが問題なく機能するようになりました。あなたはtype = "MPI"snow::makeCluster()デフォルト値を取得doSNOWあなたがロードした場合、一方

さて、上記、type = "PSOCK"parallel::makeCluster()たデフォルトを使用しています。残念ながら、将来のパッケージ用に完全なMPI backend is yet not implementedです。したがって、MPIソリューションを探しているなら、これはあなたを(まだ)助けません。

+0

これは非常に便利です!私は確かにこれをもう少し調べていくつもりですが、質問を開いたままにして、コアの問題をよりよく理解できるようにします。 – bigfoot56

関連する問題