議論の中で、「小さな」タスクが発生しました。それは、ローンポートフォリオの構造のダイナミクス(たとえば、クレジットカードのダイナミクス)を構築することです。重要な特異性があります-ローンを返済するためにFIFO法を適用する必要があります。それら。返済するときは、最も早いローンを最初に返済する必要があります。これは、個々のローンのステータスを計算し、その満期日を決定する際に特定の要件を課します。
それをオリンピックの問題と考えてください。「血まみれのエネルギー賞」やコードペダリングはなく、アプローチはもっぱら「最初に考える」ことです。プロトタイプごとに1画面のコードのみで、ループはありません(パフォーマンスと読みやすさのために埋め込まれています)。以下は、プロトタイプアプローチを使用したRコードです。
これは、以前の一連の出版物の続きです。
分解
すべてをゼロから行うため、タスクを3つのステップに分割します。
- テストデータの形成。
- 各ローンの満期日の計算。
- 特定の時間枠のダイナミクスの計算と視覚化。
プロトタイプの前提条件と規定:
- 最新の粒度。1つの日付に1つのトランザクションのみ。1日に複数のトランザクションがある場合は、それらの順序を確立する必要があります(FIFOの原則に準拠するため)。addを使用できます。インデックス、unixtimestampを使用でき、他の何かを思い付くことができます。これはプロトタイプには関係ありません。
- 明示的なループがあって
for
はなりません。不要なコピーがあってはなりません。最小のメモリ消費と最大のパフォーマンスに焦点を合わせます。 - 次の遅延グループを検討します:「<0」、「0-30」、「31-60」、「61-90」、「90+」。
ステップ1.データセットを生成する
単なるテストデータセットであり、すべての一致はランダムです。ユーザーごとに、最大10個のレコードを生成します。計算では、ローンは正の値であり、返済は負の値であると想定しています。そして、各ユーザーのライフサイクル全体はローンから始める必要があります。
library(tidyverse)
library(lubridate)
library(magrittr)
library(tictoc)
library(data.table)
total_users <- 100
events_dt <- tibble(
date = sample(
seq.Date(as.Date("2021-01-01"), as.Date("2021-04-30"), by = "1 day"),
total_users * 10,
replace = TRUE)
) %>%
# 50 .
mutate(amount = (runif(n(), -2000, 1000)) %/% 50 * 50) %>%
#
mutate(user_id = sample(!!total_users, n(), replace = TRUE)) %>%
setDT(key = "date") %>%
#
.[.[, .I[1L], by = user_id]$V1, amount := abs(amount)] %>%
# ,
#
#
unique(by = c("user_id", "date"))
ステップ2.各ローンの満期日を計算します
data.table
関数内でも参照によりオブジェクトを変更できるので、積極的に活用していきます。
#
accu_dt <- events_dt[amount < 0, .(accu = cumsum(amount), date), by = user_id]
ff <- function(dt){
#
#
accu_dt[dt, amount := i.amount, on = "user_id"]
accu_dt[is.na(amount) == FALSE, accu := accu + amount][accu > 0, accu := NA, by = user_id]
calc_dt <- accu_dt[!is.na(accu), head(date, 1), by = user_id]
# data.frame,
calc_dt[dt, on = "user_id"]$V1
}
repay_dt <- events_dt[amount > 0] %>%
.[, repayment_date := ff(.SD), by = date] %>%
.[order(user_id, date)]
ステップ3.期間中の構造のダイナミクスの計算
calcDebt <- function(report_date){
as_tibble(repay_dt) %>%
# ,
filter(is.na(repayment_date) | repayment_date > !! report_date) %>%
mutate(delay = as.numeric(!!report_date - date)) %>%
#
mutate(tag = santoku::chop(delay, breaks = c(0, 31, 61, 90),
labels = c("< 0", "0-30", "31-60", "61-90", "90+"),
extend = TRUE, drop = FALSE)) %>%
#
group_by(tag) %>%
summarise(amount = sum(amount)) %>%
mutate_at("tag", as.character)
}
#
df <- seq.Date(as.Date("2021-04-01"), as.Date("2021-04-30"), by = "1 day") %>%
tibble(date = ., tbl = purrr::map(., calcDebt)) %>%
unnest(tbl)
#
ggplot(df, aes(date, amount, colour = tag)) +
geom_point(alpha = 0.5, size = 3) +
geom_line() +
ggthemes::scale_colour_tableau("Tableau 10") +
theme_minimal()
このようなものを手に入れることができます。

必要に応じて、1画面のコード。
前の投稿- 「BI対読み聞かせR報告書、実用的なアプローチ。」