2017-06-29 8 views
1

私は、Rがどのように返品が人の年金口座に影響するかを調査するためにRを使用しています。これを行うために、私は年金勘定の発展を25歳から1000歳の退職シナリオについて70歳の退職まで計算しています。私は費用(e)、毎月の預金(m)、パーセント(r)でのリターン、口座残高(y)とユーロ(x)でのリターンを変数を使用しています。これらはすべて46x1000のデータフレームに格納されます。コードの速度を上げるためにRのforループを置き換えてください

私はそれをforループを使って計算することに成功しました。しかし、これは非常に遅く、私はこれらの多くをやっているので、誰かがコードをスピードアップするアイディアを持っているのだろうかと思っています。私は適用関数とベクトル化を試しましたが、それを動作させることはできません。私の問題は、年iの数字を計算してから年i + 1の数字を計算する必要があることです。私は解決策をインターネットで検索しましたが、私の特定の問題に適用される回答を見つけるのは難しいです。私はまだAが使用してコードイムの簡易版を書かれている

R.

にかなり新たなんだということに注意してください:

for (i in 3:46) { 
x[i-1,]<-(y[i-1,]+m[i-1,]*6-0.5*e[i-1,])*r[i-1,] 
y[i,]<-y[i-1,]+x[i-1,]-e[i-1,]+m[i-1,]*12 
} 

私は、誰かが助けることができており、事前に感謝を願っています。

敬具 ラスマス

+1

'RCpp'パッケージを使用して、' C++ 'で計算を書くことができます。このようにすれば、優れたパフォーマンスが保証され、コードの移行が非常に簡単になります。 –

+1

これをチェックしてください:https://stackoverflow.com/questions/2908822/speed-up-the-loop-operation-in-r/8474941#8474941質問と回答の両方がとても良いです。 – p0bs

答えて

4

各反復は、その前に1に依存しているため、それは、ループを必要とするようにあなたのプロセスは、私には見えます。 @ Gregor de Cilliaがコメントに言及しているように、あなたはC++でスピードの向上を図ることができます。

まず、データを設定します。

set.seed(1) 
e <- matrix(data = rnorm(n = 46000, mean = 1000, sd = 200), 
         nrow = 46, 
         ncol = 1000) 
m <- matrix(data = rnorm(n = 46000, mean = 2000, sd = 200), 
         nrow = 46, 
         ncol = 1000) 
r <- matrix(data = rnorm(n = 46000, mean = 4, sd = 0.5), 
         nrow = 46, 
         ncol = 1000) 
x <- matrix(data = NA_real_, nrow = 45, ncol = 1000) 
y <- matrix(data = NA_real_, nrow = 46, ncol = 1000) 
y[1,] <- rnorm(n = 1000, 10000, 1000) 

RcppファイルでC++関数を定義します。これは二つの行列xとリスト項目としてyでリストを返します:

List pension(NumericMatrix e, 
       NumericMatrix m, 
       NumericMatrix r, 
       NumericVector yfirstrow) { 

    int ncols = e.cols(); 
    int nrows = e.rows(); 

    NumericMatrix x(nrows - 1, ncols); 
    NumericMatrix y(nrows, ncols); 

    y(0, _) = yfirstrow; 

    for(int i = 1; i < nrows; i++) { 
     x(i-1, _) = (y(i-1, _) + m(i-1, _) * 6 - 0.5 * e(i-1, _)) * r(i-1, _); 
     y(i, _) = y(i-1, _) + x(i-1, _) - e(i-1, _) + m(i-1, _)* 12; 
    }; 

    List ret; 
    ret["x"] = x; 
    ret["y"] = y; 

    return ret; 

} 

はスピードの2つの方法を比較してください。

microbenchmark::microbenchmark(
    R = { 
     for (i in 2:46) { 
      x[i-1,] <- unlist((y[i-1,] + m[i-1,]*6 - 0.5*e[i-1,]) * r[i-1,]) 
      y[i,]<- unlist(y[i-1,]+x[i-1,]-e[i-1,]+m[i-1,]*12) 
     } 
    }, 
    cpp = { 
     cppList <- pension(e, m, r, y[1,]) 
    }, 
    times = 100 
) 

必ず出力が一致を行います。

> identical(x, cppList$x) 
[1] TRUE 
> identical(y, cppList$y) 
[1] TRUE 

スピードテストの結果:

Unit: microseconds 
expr  min  lq  mean median  uq  max neval 
    R 3309.962 3986.569 6961.838 5244.479 6219.215 96576.592 100 
    cpp 879.713 992.229 1266.014 1124.345 1273.691 3041.966 100 

のでRcppソリューションはより速く、ここで5倍程度であるが、正直に言うと、Rループあなたが作ったデータセットに対してあまり目立たないことはありません(反復回数が45回で、Rループのオーバーヘッドはあまり大きな障害ではありません)。本当にスピードが必要な場合は、C++が役に立ちます。

+0

お返事ありがとうございます、私はそれを見て、うまくいけば私の問題を解決します。私の例ではループは長い時間がかかりませんが、私のコードにはループのような複雑なループがありますが、私の例ではループを数回実行する必要があります。時間。 – Rasmus

+0

私のコメントを答えに変えてくれてありがとう:)。ちょうど発言:列方向の計算( 'y [、i] < - unlist(...')は 'R'の内部記憶モデルのために少し良いかもしれません。このテストケースでは、違いは測定できませんでした。 –

+0

@GregordeCillia申し訳ありませんが(テキストの皮肉や不足を検出するのは難しいです)。\ n行ごとの比較と列ごとの計算では異なる内部保存方法がありますか? data.frames(つまりリスト項目としての列)や行列だけを意味するのでしょうか? – rosscova

関連する問題