[英]Calculate weighted average life in R
我想計算貸款的加權平均壽命(WAL)隨着時間的推移R.計算WAL給出的公式在這里 。
我在R中創建了以下示例數據
樣本數據
library(data.table)
DT<-data.table(date=c(rep(seq(from = 2015, to = 2016.25,by = .25),2),
seq(from = 2015, to = 2017.5,by = .5)),
value=c(rep(100,5), 0, 100, 80, 60, 40, 20, 0, 100, 70, 40, 30, 20, 0),
id=rep(c("a","b","c"),each=6))
DT
date value id
1: 2015.00 100 a
2: 2015.25 100 a
3: 2015.50 100 a
4: 2015.75 100 a
5: 2016.00 100 a
6: 2016.25 0 a
7: 2015.00 100 b
8: 2015.25 80 b
9: 2015.50 60 b
10: 2015.75 40 b
11: 2016.00 20 b
12: 2016.25 0 b
13: 2015.00 100 c
14: 2015.50 70 c
15: 2016.00 40 c
16: 2016.50 30 c
17: 2017.00 20 c
18: 2017.50 0 c
因此,此示例中的每筆貸款的到期日為5年,到期日貸款完全攤銷。 注意:日期並不總是遞增一個半年或四分之一,但可能會有所不同(請參閱示例數據)。
為了計算WAL,我創建了以下R代碼
Counter <- unique(DT$id)
# LOOP OVER ID
for (i in 1:length(Counter)) {
# SUBSET ONE ID
DTSub <- DT[id == Counter[i], ]
# LOOP OVER THE AMORTIZATIONDATES
CounterSub <- unique(DTSub$date)
for (j in 1:length(CounterSub)) {
# SUBSET RANGE OF DATES IN COUNTERSUB
DTSub_Date <- DTSub[date >= CounterSub[j], ]
DTSub_Date[, t := abs(min(date)-date)]
DT[id == Counter[i] & date == CounterSub[j],
wal_calc := round(sum(abs(diff(DTSub_Date$value))
/ max(DTSub_Date$value) * DTSub_Date$t[2:nrow(DTSub_Date)]),3)]
}
}
代碼的輸出
DT
date value id wal_calc
1: 2015.00 100 a 1.250
2: 2015.25 100 a 1.000
3: 2015.50 100 a 0.750
4: 2015.75 100 a 0.500
5: 2016.00 100 a 0.250
6: 2016.25 0 a 0.000
7: 2015.00 100 b 0.750
8: 2015.25 80 b 0.625
9: 2015.50 60 b 0.500
10: 2015.75 40 b 0.375
11: 2016.00 20 b 0.250
12: 2016.25 0 b 0.000
13: 2015.00 100 c 1.300
14: 2015.50 70 c 1.143
15: 2016.00 40 c 1.125
16: 2016.50 30 c 0.833
17: 2017.00 20 c 0.500
18: 2017.50 0 c 0.000
代碼的輸出是正確的( wal_calc
),但使用雙for
環,因此是比較大的數據集(礦具有77K行和200列)慢。
第一個for
循環子集ID和第二個子集未來日期(通過id,基於第一個子集)。
請求
我希望能夠以更快,更有效的方式在這個樣本數據上生成WALS ,並避免這種雙循環。 這個問題可能有一個非常簡單的解決方案。
如果有任何不清楚的地方,請告訴我。
這將在沒有for
循環的情況下for
。
DT[order(date), WAL := {
pmts <- matrix(value[-.N] - value[-1L],
nrow = n2 <- .N - 1L, ncol = n2)
ts <- matrix(date[-1L] - date[-.N], nrow = n2, ncol = n2)
ts[upper.tri(ts)] <- 0
ts <- apply(ts, 2, cumsum)
c(colSums(pmts * ts) / value[-.N], 0)}, by = id]
DT
date value id WAL
# 1: 2015.00 100 a 1.2500000
# 2: 2015.25 100 a 1.0000000
# 3: 2015.50 100 a 0.7500000
# 4: 2015.75 100 a 0.5000000
# 5: 2016.00 100 a 0.2500000
# 6: 2016.25 0 a 0.0000000
# 7: 2015.00 100 b 0.7500000
# 8: 2015.25 80 b 0.6250000
# 9: 2015.50 60 b 0.5000000
# 10: 2015.75 40 b 0.3750000
# 11: 2016.00 20 b 0.2500000
# 12: 2016.25 0 b 0.0000000
# 13: 2015.00 100 c 1.3000000
# 14: 2015.50 70 c 1.1428571
# 15: 2016.00 40 c 1.1250000
# 16: 2016.50 30 c 0.8333333
# 17: 2017.00 20 c 0.5000000
# 18: 2017.50 0 c 0.0000000
您可以使用apply
代替第一個子集。 然后你只需要for循環。
ids <- unique(DT$id)
DTSub <- apply(DT, 1, function(x) if x$id %in% ids)
CounterSub <- unique(DTSub$date)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.