4

各行がローンであるビッグデータセット(約20万行)があります。ローンの金額、支払い回数、ローンの支払いがあります。ローンの利率を取得しようとしています。Rにはこれを計算する関数がありません(少なくともベースRにはありません、そして私はそれを見つけることができませんでした)。npv関数とirr関数の両方を作成するのはそれほど難しくありません

Npv <- function(i, cf, t=seq(from=0,by=1,along.with=cf)) sum(cf/(1+i)^t)
Irr <- function(cf) { uniroot(npv, c(0,100000), cf=cf)$root }

そして、あなたはただすることができます

rate = Irr(c(amt,rep(pmt,times=n)))

問題は、多くの支払いのレートを計算しようとするときです。unirootはベクトル化されておらず、repには驚くほどの時間がかかるため、計算が遅くなります。あなたがいくつかの数学をして、あなたが次の方程式の根を探していることを理解するならば、あなたはそれをより速くすることができます

zerome <- function(r) amt/pmt-(1-1/(1+r)^n)/r

次に、それをunirootの入力として使用します。これは、私のPCでは、200kデータベースで実行するのに約20秒かかります。

問題は、私がいくつかの最適化を行おうとしていることです。これは最適化のステップであるため、さらに高速化しようとしています。

ベクトル化を試みましたが、unirootがベクトル化されていないため、それ以上進むことはできません。ベクトル化された求根法はありますか?

ありがとう

4

1 に答える 1

7

ルートファインダーを使用する代わりに、線形補間器を使用できます。n(残りの支払いの数)の値ごとに1つの補間器を作成する必要があります。各補間器はにマップ(1-1/(1+r)^n)/rされrます。もちろんr、許容できる精度レベルに戻るように、十分に細かいグリッドを作成する必要があります。このアプローチの良い点は、線形補間器が高速でベクトル化されていることnです。対応する補間器への1回の呼び出しで、残りの支払い回数()が同じであるすべてのローンの金利を見つけることができます。

今、それが実行可能な解決策であることを証明するいくつかのコード:

まず、次の可能な値ごとに1つずつ補間器を作成しますn

n.max <- 360L  # 30 years

one.interpolator <- function(n) {
    r <- seq(from = 0.0001, to = 0.1500, by = 0.0001)
    y <- (1-1/(1+r)^n)/r
    approxfun(y, r)
}

interpolators <- lapply(seq_len(n.max), one.interpolator)

1/100パーセント(1bp)の精度を使用したことに注意してください。

次に、いくつかの偽のデータを作成します。

n.loans <- 200000L
n     <- sample(n.max, n.loans, replace = TRUE)
amt   <- 1000 * sample(100:500, n.loans, replace = TRUE)
pmt   <- amt / (n * (1 - runif(n.loans)))
loans <- data.frame(n, amt, pmt)

最後に、次のことを解きrます。

library(plyr)
system.time(ddply(loans, "n", transform, r = interpolators[[n[1]]](amt / pmt)))
#    user  system elapsed 
#   2.684   0.423   3.084

これは速い。一部の出力レートはNAそうであることに注意してください。これは、ランダム入力が意味をなさず、選択した[0〜15%]グリッド外のレートを返したためです。実際のデータにはその問題はありません。

于 2012-12-13T22:51:24.557 に答える