Evaluación de la estructura de la cartera de préstamos en R

Durante las discusiones, surgió una "pequeña" tarea: construir la dinámica de la estructura de la cartera de préstamos (dinámica de una tarjeta de crédito, por ejemplo). Hay una especificidad importante: es necesario aplicar el método FIFO para reembolsar préstamos. Esos. al reembolsar, los primeros préstamos deben reembolsarse primero. Esto impone ciertos requisitos para calcular el estado de cada préstamo individual y determinar su fecha de vencimiento.







Considérelo como un problema de Olimpiada. Sin " premios de energía sangrientos " y pedaleo de código, el enfoque es exclusivamente " pensar primero ". No más de una pantalla de código por prototipo y sin bucles (integrado para mejorar el rendimiento y la legibilidad). A continuación se muestra el código R con un enfoque de prototipo.







Es una continuación de una serie de publicaciones anteriores .







Descomposición



Como hacemos todo desde cero, dividimos la tarea en tres pasos:







  1. Formación de datos de prueba.
  2. Cálculo de la fecha de vencimiento de cada préstamo.
  3. Cálculo y visualización de dinámicas para una ventana de tiempo determinada.


Supuestos y disposiciones para el prototipo:







  1. Granularidad actualizada. Solo una transacción en una fecha. Si hay varias transacciones en un día, será necesario establecer su orden (para cumplir con el principio FIFO). Puede usar add. índices, puede usar unixtimestamp, puede pensar en algo más. Esto es irrelevante para el prototipo.
  2. No for



    debería haber ningún bucle explícito . No debe haber copias innecesarias. Céntrese en el consumo mínimo de memoria y el máximo rendimiento.
  3. Consideraremos los siguientes grupos de retrasos: "<0", "0-30", "31-60", "61-90", "90+".


Paso 1. Generar el conjunto de datos



Solo un conjunto de datos de prueba, todas las coincidencias son aleatorias. Para cada usuario, generaremos ~ 10 registros. Para los cálculos, asumimos que el préstamo es un valor positivo, el reembolso es negativo. Y el ciclo de vida completo de cada usuario debe comenzar con un préstamo.







Generación de conjuntos de datos
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"))
      
      





Paso 2. Calcule la fecha de vencimiento de cada préstamo.



data.table



le permite cambiar objetos por referencia incluso dentro de funciones, lo usaremos activamente.







Cálculo de la fecha de vencimiento
#  
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)]
      
      





Paso 3. Cálculo de la dinámica de la estructura para el período.



Cálculo de dinámica
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()
      
      





Podemos conseguir algo como esto.







Una pantalla de código, según sea necesario.







Entrada anterior - "Informe Storytelling R vs. BI, un enfoque pragmático" .








All Articles