计算R中的加权平均寿命
Calculate weighted average life in R
我想在 R 中计算贷款的加权平均寿命 (WAL)。计算 WAL[=47= 的公式] 给出 here。
我在 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 循环。这个问题可能有一个非常简单的解决方案。
如果有任何不清楚的地方,请告诉我。
您可以对第一个子集使用 apply
。然后你只需要 for 循环。
ids <- unique(DT$id)
DTSub <- apply(DT, 1, function(x) if x$id %in% ids)
CounterSub <- unique(DTSub$date)
这将在没有 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
我想在 R 中计算贷款的加权平均寿命 (WAL)。计算 WAL[=47= 的公式] 给出 here。
我在 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 循环。这个问题可能有一个非常简单的解决方案。
如果有任何不清楚的地方,请告诉我。
您可以对第一个子集使用 apply
。然后你只需要 for 循环。
ids <- unique(DT$id)
DTSub <- apply(DT, 1, function(x) if x$id %in% ids)
CounterSub <- unique(DTSub$date)
这将在没有 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