Während der Diskussionen entstand eine "kleine" Aufgabe - die Dynamik der Struktur des Kreditportfolios aufzubauen (zum Beispiel die Dynamik einer Kreditkarte). Es gibt eine wichtige Besonderheit - es ist notwendig, die FIFO-Methode anzuwenden, um Kredite zurückzuzahlen. Jene. Bei der Rückzahlung sollten die frühesten Kredite zuerst zurückgezahlt werden. Dies stellt bestimmte Anforderungen an die Berechnung des Status jedes einzelnen Kredits und die Bestimmung seines Fälligkeitsdatums.
Betrachten Sie es als ein Olympiadenproblem. Keine „ blutigen Energiepreise “ und kein Code-Pedalieren, der Ansatz ist ausschließlich „ zuerst denken “. Nicht mehr als ein Codebildschirm pro Prototyp und keine Schleifen (eingebettet in Leistung und Lesbarkeit). Unten ist der R-Code mit einem Prototyp-Ansatz.
Es ist eine Fortsetzung einer Reihe früherer Veröffentlichungen .
Zersetzung
Da wir alles von Grund auf neu machen, teilen wir die Aufgabe in drei Schritte:
- Bildung von Testdaten.
- Berechnung des Fälligkeitstermins jedes Darlehens.
- Berechnung und Visualisierung der Dynamik für ein bestimmtes Zeitfenster.
Annahmen und Bestimmungen für den Prototyp:
- Granularität auf dem neuesten Stand. Nur eine Transaktion an einem Datum. Wenn an einem Tag mehrere Transaktionen stattfinden, muss deren Reihenfolge festgelegt werden (um dem FIFO-Prinzip zu entsprechen). Sie können add verwenden. Indizes, Sie können unixtimestamp verwenden, Sie können sich etwas anderes einfallen lassen. Dies ist für den Prototyp irrelevant.
- Es
for
sollte keine expliziten Schleifen geben . Es sollten keine unnötigen Kopien vorhanden sein. Konzentrieren Sie sich auf minimalen Speicherverbrauch und maximale Leistung. - Wir werden die folgenden Gruppen von Verzögerungen betrachten: "<0", "0-30", "31-60", "61-90", "90+".
Schritt 1. Generieren des Datensatzes
Nur ein Testdatensatz, alle Übereinstimmungen sind zufällig. Für jeden Benutzer werden ~ 10 Datensätze generiert. Für Berechnungen gehen wir davon aus, dass das Darlehen einen positiven Wert hat, die Rückzahlung negativ ist. Und der gesamte Lebenszyklus für jeden Benutzer sollte mit einem Darlehen beginnen.
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"))
Schritt 2. Berechnen Sie das Fälligkeitsdatum jedes Darlehens
data.table
ermöglicht es Ihnen, Objekte auch innerhalb von Funktionen durch Referenz zu ändern, wir werden dies aktiv nutzen.
#
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)]
Schritt 3. Berechnung der Dynamik der Struktur für den Zeitraum
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()
Wir können so etwas bekommen.

Ein Codebildschirm nach Bedarf.
Vorheriger Beitrag - "Storytelling R Report vs. BI, ein pragmatischer Ansatz . "