2016-03-31 9 views
15

目標do.call

私はパラメータのグリッド上でシミュレーションを実行するためにdplyr使用することなく、パラメータのグリッド上でシミュレーションを実行するために、標準的な評価とDO_を使用しました。具体的には、私は、引数

  • はまた、いくつかを渡されたとして、私は

    • は、行ごとにdata.frame
    • を渡されることを他のプログラムで使用できる機能は、各列を使用して、いくつかのシミュレーションを計算したいと思います余分なデータ(例えば、初期条件)

    ここに私のアプローチは

    require(dplyr) 
    run <- function(data, fun, fixed_parameters, ...) { 
        ## .... 
        ## argument checking 
        ## 
    
        fixed_parameters <- as.environment(fixed_parameters) 
        grouped_out <- do_(rowwise(data), ~ do.call(fun, c(., fixed_parameters, ...))) 
        ungroup(grouped_out) 
    } 
    

    THさん作品です。 do.callせずにそれを行うための方法がありますたとえば、

    growth <- function(n, r, K, b) { 
        # some dynamical simulation 
        # this is an obviously-inefficient way to do this ;) 
        n + r - exp(n)/K - b - rnorm(1, 0, 0.1) 
    } 
    growth_runner <- function(r, K, b, ic, ...) { 
        # a wrapper to run the simulation with some fixed values 
        n0 = ic$N0 
        T = ic$T 
        reps = ic$reps 
        data.frame(n_final = replicate(reps, {for(t in 1:T) { 
                  n0 <- growth(n0, r, K, b) 
                 }; 
                 n0}) 
    ) 
    } 
    

    のために私は疑問に思う、これが動作しているようにもかかわらず

    data <- expand.grid(b = seq(0.01, 0.5, length.out=10), 
             K = exp(seq(0.1, 5, length.out=10)), 
             r = seq(0.5, 3.5, length.out=10)) 
        initial_data = list(N0=0.9, T=5, reps=20) 
        output <- run(data, growth_runner, initial_data) 
    

    質問、

    を定義して実行することができます。 (部分的にはissues with do.callのため)

    私は実際にdo.callのない同じことをする何かにgrouped_out <- do_(rowwise(data), ~ do.call(fun, c(., fixed_parameters, ...)))という行を置き換える方法に興味があります。 編集:上記のリンクで概説したdo.callを使用した場合のパフォーマンス上の不利益を何とか回避するアプローチも有効です。

    ノートや参考文献が

  • +1

    FWIWは 'plyr :: mdply'とまったく同じように聞こえる。残念ながら、2つのパッケージはどちらかというと互換性がありません。 – baptiste

    +0

    ダグ、私は 'plyr'のその部分を発見したことがない!ポインタのおかげで – jaimedash

    +1

    私はあなたがおそらく 'purrr :: invoke_rows'を望んでいると思います。これは' mdply'の現代的なものです。 http://rpackages.ianhowson.com/cran/purrr/man/by_row.html – Shorpy

    答えて

    1

    の代わりに働くことができると思います以下do.callを使用して回避し、OPと同じように出力を提示しています。

    まず、関数のパラメータを、渡すベクトルで置き換えます。これは、applyを使用して渡すものです。

    growth_runner <- function(data.in, ic, ...) { 
        # a wrapper to run the simulation with some fixed values 
        n0 = ic$N0 
        T = ic$T 
        reps = ic$reps 
        data.frame(n_final = replicate(reps, {for(t in 1:T) { 
        n0 <- growth(n0, data.in[3], data.in[2], data.in[1]) 
        }; 
        n0}) 
    ) 
    } 
    

    以前と同じように、検索するグリッドを設定します。

    data <- expand.grid(b = seq(0.01, 0.5, length.out=10), 
            K = exp(seq(0.1, 5, length.out=10)), 
            r = seq(0.5, 3.5, length.out=10)) 
    initial_data = list(N0=0.9, T=5, reps=20) 
    

    使用することは、あなたのグリッドを通過して、結果

    output.mid = apply(data, 1, ic=initial_data, FUN=growth_runner) 
    output <- data.frame('n_final'=unlist(output.mid)) 
    

    を追加し、あなたがdo.callへの呼び出し、または任意の外部ライブラリなしで、あなたの出力を持つように適用されます。

    > dim(output) 
    [1] 20000  1 
    > head(output) 
        n_final 
    1 -0.6375070 
    2 -0.7617193 
    3 -0.3266347 
    4 -0.7921655 
    5 -0.5874983 
    6 -0.4083613 
    
    +0

    申し訳ありません、あなたは質問の重要な文脈がありません:using dplyr。 (質問の最初の行)。 5/19の編集はこれを明確にします。これは、より一般的でない方法で同じ全体的なタスクを達成するのにも役立つコードです。ありがとう! – jaimedash

    +0

    また、数値以外のパラメータを持つとすぐに 'apply()'が失敗することに注意してください。 – hadley

    0

    あなたは(purrr:invoke_rows()を指摘し@shorpyに感謝)以下とdo.callの行を置き換えることができます。

    grouped_out <- purrr::invoke_rows(fun, dplyr::rowwise(data), fixed_parameters) 
    

    を、他に変更を加えることなく、これはとのデータフレームを与えますdata.framesの列など

    Source: local data frame [1,000 x 4] 
          b  K  r    .out 
         (dbl) (dbl) (dbl)    (chr) 
    1 0.01000000 1.105171 0.5 <data.frame [20,1]> 
    2 0.06444444 1.105171 0.5 <data.frame [20,1]> 
    3 0.11888889 1.105171 0.5 <data.frame [20,1]> 
    

    元の動作に近いものを復元するには、電子

    Source: local data frame [20,000 x 4] 
    
         b  K  r n_final 
        (dbl) (dbl) (dbl)  (dbl) 
    1 0.01 1.105171 0.5 -0.6745470 
    2 0.01 1.105171 0.5 -0.7500365 
    3 0.01 1.105171 0.5 -0.6568312 
    

    を与える

    dplyr::ungroup(tidyr::unnest(grouped_out, .out)) 
    

    runの最後の行は、コードの他の変更は必要ありません:)

    +0

    'invoke_rows()'がこの世界では長くないかもしれないので、私はそれに頼らないでしょう。 – hadley

    +1

    代わりに 'pmap'を見てみましょう(あなたの答えのように) – jaimedash

    5

    を私はあなたのコードに従うこと、それは少しトリッキー見つけましたが、私は思いますこれは同等です。

    まず、私はあなたが興味を持っている計算ない機能定義:

    growth_t <- function(n0, r, K, b, T) { 
        n <- n0 
    
        for (t in 1:T) { 
        n <- n + r - exp(n)/K - b - rnorm(1, 0, 0.1) 
        } 
        n 
    } 
    

    は、その後、私は担当者のための「ダミー」変数を含め、あなたが変化するようにしたいデータを定義する:

    data <- expand.grid(
        b = seq(0.01, 0.5, length.out = 5), 
        K = exp(seq(0.1, 5, length.out = 5)), 
        r = seq(0.5, 3.5, length.out = 5), 
        rep = 1:20 
    ) 
    

    それから私はそれをpurrr::pmap_d()に入れることができます。 pmap_d()は、「パラレル」マップを実行します。つまり、リスト(またはデータフレーム)を入力として受け取り、各反復ごとにすべての名前付き引数を変更する関数を呼び出します。固定パラメータは、関数名の後に指定します。それはデータ操作については、実際にはないので

    library(purrr) 
    data$output <- pmap_dbl(data[1:3], growth_t, n0 = 0.9, T = 5) 
    

    これは本当に、私にはdplyrの問題のように感じることはありません。

    +0

    ありがとう! fair point re dplyr、それは 'dplyr :: do'で始まりました。しかし、きちんとしたデータ、特にあなたが 'purrr '(例えば、http://stackoverflow.com/q/35505187/4598520)に向かう方向にツールを拡張すると、それはおそらく、きちんとしたデータ問題 – jaimedash