Introducción
En el mundo dinámico de la banca y las finanzas, el análisis de riesgo es una piedra angular para la toma de decisiones informadas. Uno de los instrumentos más valiosos en este análisis es el Population Stability Index (PSI), una medida que permite a las instituciones financieras evaluar la estabilidad de sus modelos predictivos a lo largo del tiempo. En la sección de Estadística hemos explorado a fondo el PSI, proporcionando una comprensión teórica y práctica de esta herramienta (puedes revisar todo el contenido en Population Stability Index).
Ahora, nos adentramos en el análisis del PSI utilizando código SAS, una habilidad crucial para los analistas y científicos de datos en el sector financiero. Aunque existen múltiples plataformas para ejecutar código SAS, recomendamos Altair SLCTM, por aquí os dejamos una guía detallada sobre cómo instalar de forma gratuita Altair SLCTM en tu PC. Todos los códigos que se muestran en esta web funcionan perfectamente en cualquier software que tenga la capacidad de compilar el lenguaje de programación SAS.
Este ejemplo ha sido cuidadosamente diseñado para mostrarte cómo realizar el análisis de PSI de manera eficiente utilizando el lenguaje de programación SAS. Para ilustrar esto, exploraremos dos ejemplos prácticos: la variable categórica «Motor de decisión» y la variable continua «PD». Ambas son esenciales en la evaluación del riesgo de impago. Únete a nosotros en este recorrido técnico y descubre cómo maximizar las capacidades de SAS para tus análisis de PSI.
Ejemplo Práctico
Imagina que te han contratado en una entidad financiera para realizar un chequeo de salud del modelo predictivo que usan para evaluar el riesgo de impago de sus clientes. La entidad está interesada en saber si el modelo todavía es fiable o si ha llegado el momento de actualizarlo con nueva información o, incluso, diseñar uno nuevo. Hay dos variables que les preocupan especialmente: «Motor de decisión» y «PD». La razón es que estas variables son clave en la toma de decisiones y, por tanto, es crucial que sus distribuciones no hayan variado significativamente desde que se desarrolló el modelo.
Por un lado, nos han facilitado la base de datos con la que se desarrolló el modelo predictivo, que cuenta con 78.760 observaciones, a partir de ahora nos referiremos a ella como base o referencia. Por otro lado, nos han proporcionado la base de datos de validación, también conocida como Oot (Out of time), que cuenta con 62.544 observaciones, a partir de ahora la llamaremos actual.
Variable categórica: «Motor de decisión»
La variable «motor_de_decision» categoriza las decisiones de préstamo en cinco grupos:
- Resto
- Empresa
- Préstamo Joven (menores de 30 años)
- Préstamo a Empleados
- Préstamo Preconcedido
Nuestro objetivo es evaluar si la distribución de estas categorías ha permanecido constante o ha cambiado con el tiempo.
¡Comencemos!
Cargar las BBDD
La entidad nos proporciona dos archivos Excel en formato .xlsx:
Lo primero que haremos será importar los conjuntos de datos a SAS:
/*Lectura del archivo BBDD_MODELO.xlsx*/
PROC IMPORT OUT=BBDD_MODELO
DATAFILE = "C:\Users\user\Desktop\BBDD_MODELO.xlsx"
DBMS = XLSX;
GETNAMES = YES;
RUN;
/*Lectura del archivo BBDD_OOT.xlsx*/
PROC IMPORT OUT=BBDD_OOT
DATAFILE = "C:\Users\user\Desktop\BBDD_OOT.xlsx"
DBMS = XLSX;
GETNAMES = YES;
RUN;
SAS👇🏻¿Dudas con alguna parte del código?
PROC IMPORT
1. PROC IMPORT: Este es el comando principal que le indica a SAS que vas a realizar una importación de datos. PROC IMPORT es utilizado para leer datos de fuentes externas y convertirlos en un conjunto de datos de SAS.
2. OUT=BBDD_MODELO: Este parámetro especifica el nombre del conjunto de datos de SAS que se creará a partir del archivo importado. En este caso, el conjunto de datos se llamará BBDD_MODELO.
3. DATAFILE = «C:\Users\user\Desktop\BBDD_MODELO.xlsx»: Este parámetro indica la ruta y el nombre del archivo que deseas importar. Aquí, se está importando un archivo llamado BBDD_MODELO.xlsx, que se encuentra en el escritorio del usuario.
4. DBMS = XLSX: Este parámetro especifica el tipo de base de datos del archivo que se va a importar. En este caso, XLSX indica que el archivo es un Excel en formato de Microsoft Office 2007 o posterior.
5. GETNAMES = YES: Este parámetro le dice a SAS que las primeras filas del archivo Excel contienen los nombres de las variables. Al establecer GETNAMES en YES, SAS utiliza la primera fila del archivo Excel para los nombres de las variables en el conjunto de datos de SAS.
6. RUN;: Finaliza la instrucción de PROC IMPORT y ejecuta el procedimiento.
Recuentos y Proporciones
A continuación, calculamos las frecuencias y los porcentajes de los distintos valores que toma la variable «motor_de_decision» en la base del modelo. También obtenemos el total de observaciones, almacenando el número en la macro variable «TOT_RECUENTO_BASE».
/*Recuentos y Proporciones de la tabla base (BBDD_MODELO)*/
/*Obtenemos las frecuencias de los distintos valores de la variable MOTOR_DE_DECISION*/
PROC SQL;
CREATE TABLE BASE_AUX AS SELECT
MOTOR_DE_DECISION,
COUNT(*) AS RECUENTO_BASE
FROM BBDD_MODELO
GROUP BY MOTOR_DE_DECISION;
QUIT;
/*Sumamos todas las frecuencias de cada categoría para obtener el total de observaciones*/
PROC SQL NOPRINT;
SELECT SUM(RECUENTO_BASE) INTO :TOT_RECUENTO_BASE
FROM BASE_AUX;
QUIT;
/*Calculamos la proporción de cada categoría*/
DATA BASE;
SET BASE_AUX;
PROPORCION_BASE = (RECUENTO_BASE/&TOT_RECUENTO_BASE);
RUN;
/*Sumamos todas las proporciones de cada categoría. Esta suma tiene que ser igual a 1*/
PROC SQL NOPRINT;
SELECT SUM(PROPORCION_BASE) INTO :TOT_PROPORCION_BASE
FROM BASE;
QUIT;
SAS👇🏻¿Dudas con alguna parte del código?
- PROC SQL;
- Inicia un procedimiento SQL en SAS para realizar consultas y manipulaciones de datos.
- CREATE TABLE BASE_AUX AS SELECT
CREATE TABLE BASE_AUX
: Crea una nueva tabla llamadaBASE_AUX
.AS SELECT
: Indica que la estructura y contenido deBASE_AUX
se basará en el resultado de la consultaSELECT
que sigue.
- MOTOR_DE_DECISION, COUNT(*) AS RECUENTO_BASE
MOTOR_DE_DECISION
: Columna seleccionada del conjunto de datosBBDD_MODELO
.COUNT(*)
: Función de agregación que cuenta todas las filas.AS RECUENTO_BASE
: Renombra el resultado deCOUNT(*)
aRECUENTO_BASE
.
- FROM BBDD_MODELO
- Especifica que los datos provienen del conjunto de datos
BBDD_MODELO
.
- Especifica que los datos provienen del conjunto de datos
- GROUP BY MOTOR_DE_DECISION;
- Agrupa los datos por cada valor único en la columna
MOTOR_DE_DECISION
.
- Agrupa los datos por cada valor único en la columna
- QUIT;
- Finaliza el bloque
PROC SQL
.
- Finaliza el bloque
- PROC SQL NOPRINT;
- Inicia otro bloque
PROC SQL
sin mostrar los resultados (output).
- Inicia otro bloque
- SELECT SUM(RECUENTO_BASE) INTO :TOT_RECUENTO_BASE FROM BASE_AUX;
SELECT SUM(RECUENTO_BASE)
: Calcula la suma total deRECUENTO_BASE
.INTO :TOT_RECUENTO_BASE
: Almacena el resultado en una macro variable llamadaTOT_RECUENTO_BASE
.FROM BASE_AUX
: Especifica que la suma se realiza sobre los datos deBASE_AUX
.
- DATA BASE;
- Crea un conjunto de datos llamado
BASE
.
- Crea un conjunto de datos llamado
- SET BASE_AUX;
- Lee y utiliza los datos del conjunto de datos
BASE_AUX
.
- Lee y utiliza los datos del conjunto de datos
- PROPORCION_BASE = (RECUENTO_BASE / &TOT_RECUENTO_BASE);
- Calcula la proporción de cada valor de
RECUENTO_BASE
con respecto al total enTOT_RECUENTO_BASE
.
- Calcula la proporción de cada valor de
- RUN;
- Ejecuta las instrucciones del bloque
DATA
.
- Ejecuta las instrucciones del bloque
- SELECT SUM(PROPORCION_BASE) INTO :TOT_PROPORCION_BASE FROM BASE;
- Calcula la suma de
PROPORCION_BASE
en el conjunto de datosBASE
y almacena el resultado en la macro variableTOT_PROPORCION_BASE
.
- Calcula la suma de
Una vez hemos calculado los valores que nos interesan, la tabla Base queda con la siguiente estructura:
Ahora hacemos lo mismo para la base Oot (out of time).
/*Recuentos y Proporciones de la tabla actual (BBDD_OOT)*/
/*Obtenemos las frecuencias de los distintos valores de la variable MOTOR_DE_DECISION*/
PROC SQL;
CREATE TABLE ACTUAL_AUX AS SELECT
MOTOR_DE_DECISION,
COUNT(*) AS RECUENTO_ACTUAL
FROM BBDD_OOT
GROUP BY MOTOR_DE_DECISION;
QUIT;
/*Sumamos todas las frecuencias de cada categoría para obtener el total de observaciones*/
PROC SQL NOPRINT;
SELECT SUM(RECUENTO_ACTUAL) INTO :TOT_RECUENTO_ACTUAL
FROM ACTUAL_AUX;
QUIT;
/*Calculamos la proporción de cada categoría*/
DATA ACTUAL;
SET ACTUAL_AUX;
PROPORCION_ACTUAL = (RECUENTO_ACTUAL/&TOT_RECUENTO_ACTUAL);
RUN;
/*Sumamos todas las proporciones de cada categoría. Esta suma tiene que ser igual a 1*/
PROC SQL NOPRINT;
SELECT SUM(PROPORCION_ACTUAL) INTO :TOT_PROPORCION_ACTUAL
FROM ACTUAL;
QUIT;
SAS👇🏻¿Dudas con alguna parte del código?
- PROC SQL;
- Inicia un procedimiento SQL en SAS para realizar consultas y manipulaciones de datos.
- CREATE TABLE ACTUAL_AUX AS SELECT
CREATE TABLE ACTUAL_AUX
: Crea una nueva tabla llamadaACTUAL_AUX
.AS SELECT
: Indica que la estructura y contenido deACTUAL_AUX
se basará en el resultado de la consultaSELECT
que sigue.
- MOTOR_DE_DECISION, COUNT(*) AS RECUENTO_ACTUAL
MOTOR_DE_DECISION
: Columna seleccionada del conjunto de datosBBDD_OOT
.COUNT(*)
: Función de agregación que cuenta todas las filas.AS RECUENTO_ACTUAL
: Renombra el resultado deCOUNT(*)
aRECUENTO_ACTUAL
.
- FROM BBDD_MODELO
- Especifica que los datos provienen del conjunto de datos
BBDD_OOT
.
- Especifica que los datos provienen del conjunto de datos
- GROUP BY MOTOR_DE_DECISION;
- Agrupa los datos por cada valor único en la columna
MOTOR_DE_DECISION
.
- Agrupa los datos por cada valor único en la columna
- QUIT;
- Finaliza el bloque
PROC SQL
.
- Finaliza el bloque
- PROC SQL NOPRINT;
- Inicia otro bloque
PROC SQL
sin mostrar los resultados (output).
- Inicia otro bloque
- SELECT SUM(RECUENTO_ACTUAL) INTO :TOT_RECUENTO_ACTUAL FROM ACTUAL_AUX;
SELECT SUM(RECUENTO_ACTUAL)
: Calcula la suma total deRECUENTO_ACTUAL
.INTO :TOT_RECUENTO_ACTUAL
: Almacena el resultado en una macro variable llamadaTOT_RECUENTO_ACTUAL
.FROM ACTUAL_AUX
: Especifica que la suma se realiza sobre los datos deACTUAL_AUX
.
- DATA ACTUAL;
- Crea un conjunto de datos llamado
ACTUAL
.
- Crea un conjunto de datos llamado
- SET ACTUAL_AUX;
- Lee y utiliza los datos del conjunto de datos
ACTUAL_AUX
.
- Lee y utiliza los datos del conjunto de datos
- PROPORCION_ACTUAL = (RECUENTO_ACTUAL / &TOT_RECUENTO_ACTUAL);
- Calcula la proporción de cada valor de
RECUENTO_ACTUAL
con respecto al total enTOT_RECUENTO_ACTUAL
.
- Calcula la proporción de cada valor de
- RUN;
- Ejecuta las instrucciones del bloque
DATA
.
- Ejecuta las instrucciones del bloque
- SELECT SUM(PROPORCION_ACTUAL) INTO :TOT_PROPORCION_ACTUAL FROM ACTUAL;
- Calcula la suma de
PROPORCION_ACTUAL
en el conjunto de datosACTUAL
y almacena el resultado en la macro variableTOT_PROPORCION_ACTUAL
.
- Calcula la suma de
La tabla Actual queda de la siguiente manera:
Cálculo del PSI
El siguiente código está diseñado para calcular el PSI de cada categoría de «motor_de_decision». Fíjate que antes de utilizar la fórmula general del PSI en la línea 9 se aplica la corrección manual de las proporciones nulas. Recuerda que el PSI tiene una deficiencia cuando se trata de proporciones nulas o cero, ya sea en las proporciones de la base o actuales. Por eso asignamos el valor 0 a las frecuencias que cuentan con valores vacíos y posteriormente recalculamos su proporción de forma manual añadiendo una observación ficticia, para que más adelante sea posible calcular el logaritmo.
/*Cálculo del PSI*/
DATA RESUMEN;
MERGE BASE ACTUAL;
BY MOTOR_DE_DECISION;
IF RECUENTO_BASE = . THEN RECUENTO_BASE = 0;
IF RECUENTO_ACTUAL = . THEN RECUENTO_ACTUAL = 0;
IF RECUENTO_BASE = 0 THEN PROPORCION_BASE = (1/&TOT_RECUENTO_BASE);
IF RECUENTO_ACTUAL = 0 THEN PROPORCION_ACTUAL = (1/&TOT_RECUENTO_ACTUAL);
PSI = (PROPORCION_ACTUAL-PROPORCION_BASE)*LOG(PROPORCION_ACTUAL/PROPORCION_BASE);
RUN;
SAS👇🏻¿Dudas con alguna parte del código?
- DATA RESUMEN;
- Crea un conjunto de datos llamado
RESUMEN
.
- Crea un conjunto de datos llamado
- MERGE BASE ACTUAL;
- Combina los conjuntos de datos
BASE
yACTUAL
en uno solo. Esta operación alinea las filas de ambos conjuntos de datos basándose en las columnas comunes especificadas en la cláusulaBY
que sigue.
- Combina los conjuntos de datos
- BY MOTOR_DE_DECISION;
- Especifica que la fusión de
BASE
yACTUAL
debe realizarse en base a la columnaMOTOR_DE_DECISION
. Esto significa que las filas de ambos conjuntos de datos se alinearán según los valores coincidentes en esta columna.
- Especifica que la fusión de
- IF RECUENTO_BASE = . THEN RECUENTO_BASE = 0;
- Reemplaza los valores faltantes (representados por
.
en SAS) en la columnaRECUENTO_BASE
con cero.
- Reemplaza los valores faltantes (representados por
- IF RECUENTO_ACTUAL = . THEN RECUENTO_ACTUAL = 0;
- Reemplaza los valores faltantes en la columna
RECUENTO_ACTUAL
con cero.
- Reemplaza los valores faltantes en la columna
- IF RECUENTO_BASE = 0 THEN PROPORCION_BASE = (1/&TOT_RECUENTO_BASE);
- Si
RECUENTO_BASE
es igual a 0, se calculaPROPORCION_BASE
como 1 dividido entre el total de recuentos de base (almacenado en la macro variable&TOT_RECUENTO_BASE
).
- Si
- IF RECUENTO_ACTUAL = 0 THEN PROPORCION_ACTUAL = (1/&TOT_RECUENTO_ACTUAL);
- Si
RECUENTO_ACTUAL
es igual a 0, se calculaPROPORCION_ACTUAL
como 1 dividido entre el total de recuentos actuales (almacenado en la macro variable&TOT_RECUENTO_ACTUAL
).
- Si
- PSI = (PROPORCION_ACTUAL – PROPORCION_BASE) * LOG(PROPORCION_ACTUAL / PROPORCION_BASE);
- Calcula el Population Stability Index (PSI) utilizando la fórmula dada. Esta fórmula mide la diferencia en las distribuciones de la población base y actual, utilizando el logaritmo natural de la proporción actual dividida por la proporción base, multiplicado por la diferencia entre estas proporciones.
- RUN;
- Ejecuta el bloque de código
DATA
.
- Ejecuta el bloque de código
La tabla resultante del código anterior es la siguiente:
Sumamos los PSIs de todas las categorías de la variable «motor_de_decision» y almacenamos el resultado final en la macro variable PSI.
/*Guardamos el valor del PSI en la macro variable PSI*/
PROC SQL NOPRINT;
SELECT SUM(PSI) INTO :PSI
FROM RESUMEN;
QUIT;
SAS👇🏻¿Dudas con alguna parte del código?
- PROC SQL NOPRINT;
PROC SQL
: Inicia un procedimiento SQL, permitiendo la ejecución de consultas y comandos SQL en SAS.NOPRINT
: Esta opción evita que los resultados de la consulta SQL se muestren en la salida. Se utiliza cuando solo se necesita realizar una acción (como crear una macro variable) sin necesidad de visualizar los resultados.
- SELECT SUM(PSI) INTO :PSI FROM RESUMEN;
SELECT SUM(PSI)
: Esta instrucción calcula la suma total de la columnaPSI
en el conjunto de datosRESUMEN
. El PSI es un valor calculado previamente en cada fila, representando el índice de estabilidad para cada valor deMOTOR_DE_DECISION
.INTO :PSI
: El resultado de la suma se almacena en una macro variable llamadaPSI
. Las macro variables en SAS se utilizan para almacenar valores que pueden ser referenciados posteriormente en el código SAS. El prefijo:
indica que se trata de una macro variable.FROM RESUMEN
: Especifica que la suma se realiza sobre los datos del conjuntoRESUMEN
.
- QUIT;
- Finaliza el bloque
PROC SQL
.
- Finaliza el bloque
Creamos la tabla de Totales, que contará con un único registro formado por las sumas de cada una de las columnas y el RAG correspondiente (es una de las métricas más utilizadas en la interpretación de resultados, que se refiere a «Red», «Amber» y «Green», puedes consultarlo en el apartado Interpretación de resultados de la explicación teórica del PSI).
/*Se crea la fila de totales*/
DATA TOTALES;
MOTOR_DE_DECISION = "TOTAL";
PSI = Ψ
RECUENTO_BASE = &TOT_RECUENTO_BASE;
RECUENTO_ACTUAL = &TOT_RECUENTO_ACTUAL;
PROPORCION_BASE = &TOT_PROPORCION_BASE;
PROPORCION_ACTUAL = &TOT_PROPORCION_ACTUAL;
IF PSI <= 0.1 THEN RAG = "G";
ELSE IF 0.1 < PSI <= 0.25 THEN RAG = "A";
ELSE IF PSI > 0.25 THEN RAG = "R";
RUN;
SAS👇🏻¿Dudas con alguna parte del código?
- DATA TOTALES;
- Crea un conjunto de datos llamado
TOTALES
.
- Crea un conjunto de datos llamado
- MOTOR_DE_DECISION = «TOTAL»;
- Asigna el valor «TOTAL» a la variable
MOTOR_DE_DECISION
. Esto indica que la fila representa los totales de la tabla.
- Asigna el valor «TOTAL» a la variable
- PSI = &PSI;
- Asigna a la variable
PSI
el valor almacenado en la macro variablePSI
. Esta macro variable contiene el valor acumulado del PSI calculado en pasos anteriores del programa.
- Asigna a la variable
- RECUENTO_BASE = &TOT_RECUENTO_BASE;
- Asigna a la variable
RECUENTO_BASE
el valor almacenado en la macro variableTOT_RECUENTO_BASE
, que representa el total de recuentos de la base.
- Asigna a la variable
- RECUENTO_ACTUAL = &TOT_RECUENTO_ACTUAL;
- Asigna a la variable
RECUENTO_ACTUAL
el valor almacenado en la macro variableTOT_RECUENTO_ACTUAL
, que representa el total de recuentos actuales.
- Asigna a la variable
- PROPORCION_BASE = &TOT_PROPORCION_BASE;
- Asigna a la variable
PROPORCION_BASE
el valor almacenado en la macro variableTOT_PROPORCION_BASE
, que representa la proporción total en la base.
- Asigna a la variable
- PROPORCION_ACTUAL = &TOT_PROPORCION_ACTUAL;
- Asigna a la variable
PROPORCION_ACTUAL
el valor almacenado en la macro variableTOT_PROPORCION_ACTUAL
, que representa la proporción total actual.
- Asigna a la variable
- IF PSI <= 0.1 THEN RAG = «G»;
- Si el valor de
PSI
es menor o igual a 0.1, asigna «G» (verde) a la variableRAG
. Esto indica una estabilidad aceptable en el modelo o la población.
- Si el valor de
- ELSE IF 0.1 < PSI <= 0.25 THEN RAG = «A»;
- Si el valor de
PSI
está entre 0.1 y 0.25, asigna «A» (ámbar) aRAG
. Esto indica una estabilidad moderada.
- Si el valor de
- ELSE IF PSI > 0.25 THEN RAG = «R»;
- Si el valor de
PSI
es mayor a 0.25, asigna «R» (rojo) aRAG
. Esto sugiere una inestabilidad significativa.
- Si el valor de
- RUN;
- Ejecuta el bloque de código
DATA
.
- Ejecuta el bloque de código
La tabla que genera el código anterior es la siguiente:
Por último, unimos las tablas Resumen y Totales en una única tabla llamada Resultado. Ordenamos las columnas en el orden deseado y le ponemos 4 decimales a las proporciones.
/*Añadimos los totales a la tabla resumen*/
DATA RESULTADO;
RETAIN MOTOR_DE_DECISION RECUENTO_BASE RECUENTO_ACTUAL PROPORCION_BASE PROPORCION_ACTUAL PSI RAG;
SET RESUMEN TOTALES;
FORMAT PROPORCION_BASE 6.4;
FORMAT PROPORCION_ACTUAL 6.4;
RUN;
SAS👇🏻¿Dudas con alguna parte del código?
- DATA RESULTADO;
- Crea un conjunto de datos llamado
RESULTADO
.
- Crea un conjunto de datos llamado
- RETAIN MOTOR_DE_DECISION RECUENTO_BASE RECUENTO_ACTUAL PROPORCION_BASE PROPORCION_ACTUAL PSI RAG;
- La instrucción
RETAIN
se utiliza para especificar el orden de las variables en el conjunto de datos resultante. Las variables listadas aquí se mantendrán en el orden en que se enumeran. Esto no afecta la lógica del programa, sino la organización y presentación de los datos en el conjunto de datosRESULTADO
.
- La instrucción
- SET RESUMEN TOTALES;
- La instrucción
SET
se utiliza para combinar los datos de dos o más conjuntos de datos. En este caso, combinaRESUMEN
yTOTALES
en el nuevo conjunto de datosRESULTADO
. La combinación se realiza apilando los registros deTOTALES
debajo de los registros deRESUMEN
.
- La instrucción
- FORMAT PROPORCION_BASE 6.4;
- Aplica un formato específico a la variable
PROPORCION_BASE
. El formato6.4
significa que la variable se mostrará con un ancho total de 6 caracteres, incluyendo 4 decimales. Por ejemplo, un número como 0.1234 se mostrará en este formato.
- Aplica un formato específico a la variable
- FORMAT PROPORCION_ACTUAL 6.4;
- Se aplica el formato
6.4
a la variablePROPORCION_ACTUAL
.
- Se aplica el formato
- RUN;
- Ejecuta el bloque de código
DATA
.
- Ejecuta el bloque de código
El resultado final es el siguiente:
Conclusión
El PSI de la variable «motor_de_decision» es:
\text{PSI} = 0,00014 + ... + 0,06992 = 0,77155
Tras analizar la variable categórica «motor_de_decision con las categorías proporcionadas y calcular el Índice de Estabilidad de la Población (PSI), hemos llegado a un valor de 0,77155. Este resultado se desglosa de la siguiente manera: una contribución mínima de la categoría «1.Resto», una significativa de «2.Empresa», la más elevada de «3.Joven», y aportaciones menores de «4.Empleado» y «5.Preconcedido».
Un PSI de 0,77 sugiere cambios sustanciales en la distribución de esta variable desde la creación del modelo. Generalmente, un PSI por debajo o igual a 0,1 indica estabilidad, entre 0,1 y 0,25 sugiere un cambio moderado, y un valor superior a 0,25 puede indicar una variación significativa que podría requerir una recalibración del modelo o incluso el desarrollo de uno nuevo. Dado que nuestro valor excede ampliamente el umbral de 0,25 se recomienda que la entidad financiera realice una revisión exhaustiva del modelo y considere actualizarlo para reflejar los patrones actuales de decisión de préstamo.
Variable continua: PD
«PD» representa la probabilidad de incumplimiento (Probability of Default) asignada por el modelo a cada cliente o contrato. Se utiliza para estimar la probabilidad de que un prestatario falle en cumplir con sus obligaciones de pago en un plazo determinado, generalmente 1 año. El valor de la «PD» varía entre 0 y 1, donde 0 indicaría que es imposible que un prestatario incumpla sus obligaciones y 1 señala que el incumplimiento es seguro.
El PSI cuantifica la variabilidad entre las distribuciones de distintas subpoblaciones o grupos; así que dividiremos la variable «PD» en 10 rangos iguales, creando así 10 categorías. Cada categoría tendrá aproximadamente la misma cantidad de observaciones. Analizaremos cómo se distribuyen los clientes de la base del modelo en estos deciles en comparación con los clientes actuales.
Si estás usando Altair Analytics Workbench el procedimiento para crear las categorías recibe el nombre de «PROC BIN» mientras que para SAS Studio el procedimiento es «PROC HPBIN». Solamente es una diferencia semántica puntual que probablemente se deba a diferencias en las filosofías del diseño del software, porque disponen de las mismas opciones dentro del procedimiento y proporcionan exactamente los mismos resultados.
Con Altair Analytics Workbench sería de la siguiente forma:
/*Creamos 10 categorías iguales para la variable PD*/
PROC BIN DATA = BBDD_MODELO OUTPUT=BASE_BUCKETIZADA NUMBIN=10 QUANTILE;
INPUT PD;
TITLE "Bucketización de la variable PD";
RUN;
SAS👇🏻¿Dudas con alguna parte del código?
- PROC BIN DATA = BBDD_MODELO OUTPUT=BASE_BUKETIZADA NUMBIN=10 QUANTILE;
PROC BIN
: Inicia el procedimientoBIN
, que es utilizado para el binning de datos.DATA = BBDD_MODELO
: Especifica el conjunto de datos de entrada, en este casoBBDD_MODELO
.OUTPUT=BASE_BUKETIZADA
: Define el nombre del conjunto de datos de salida que contendrá los resultados del binning. En este caso, el conjunto de datos resultante se llamaráBASE_BUKETIZADA
.NUMBIN=10
: Indica que los datos se deben dividir en 10 categorías o buckets.QUANTILE
: Esta opción especifica que el método de binning debe basarse en cuantiles. Esto significa que cada categoría tendrá aproximadamente la misma cantidad de observaciones.
- INPUT PD;
INPUT PD;
: Especifica la variable que se va a utilizar para el binning, en este caso,PD
.
- TITLE «Bucketización de la variable PD»;
TITLE
: Establece un título para los resultados o salidas del procedimiento. Aquí, el título es «Bucketización de la variable PD».
- RUN;
- Ejecuta el procedimiento
BIN
.
- Ejecuta el procedimiento
Al ejecutar el procedimiento anterior se muestra el siguiente resultado:
El reporte muestra la información general de la bucketización realizada (método utilizado, número de buckets y número de variables bucketizadas) y una tabla resumen con los límites, frecuencias y proporciones de cada bucket. También muestra el nombre de la nueva variable bucketizada que es «BIN_nombrevariable«.
Con SAS Studio sería de la siguiente forma:
/*Creamos 10 categorías iguales para la variable PD*/
PROC HPBIN DATA = BBDD_MODELO OUTPUT=BASE_BUCKETIZADA NUMBIN=10 QUANTILE;
INPUT PD;
TITLE "Bucketización de la variable PD";
RUN;
SAS👇🏻¿Dudas con alguna parte del código?
- PROC HPBIN DATA = BBDD_MODELO OUTPUT=BASE_BUKETIZADA NUMBIN=10 QUANTILE;
PROC HPBIN
: Inicia el procedimientoHPBIN
, que es utilizado para el binning de datos.DATA = BBDD_MODELO
: Especifica el conjunto de datos de entrada, en este casoBBDD_MODELO
.OUTPUT=BASE_BUKETIZADA
: Define el nombre del conjunto de datos de salida que contendrá los resultados del binning. En este caso, el conjunto de datos resultante se llamaráBASE_BUKETIZADA
.NUMBIN=10
: Indica que los datos se deben dividir en 10 categorías o buckets.QUANTILE
: Esta opción especifica que el método de binning debe basarse en cuantiles. Esto significa que cada categoría tendrá aproximadamente la misma cantidad de observaciones.
- INPUT PD;
INPUT PD;
: Especifica la variable que se va a utilizar para el binning, en este caso,PD
.
- TITLE «Bucketización de la variable PD»;
TITLE
: Establece un título para los resultados o salidas del procedimiento. Aquí, el título es «Bucketización de la variable PD».
- RUN;
- Ejecuta el procedimiento
HPBIN
.
- Ejecuta el procedimiento
El reporte es idéntico al anterior:
Ya estés utilizando Altair Analytics Workbench o SAS Studio obtendrás exactamente el mismo resultado. La tabla «BASE_BUCKETIZADA» que resulta tras ejecutar el procedimiento queda de la siguiente manera:
Recuentos y Proporciones
Una vez hemos creado la variable «BIN_PD», el proceso para la obtención de su PSI será igual que con la variable «motor_de_decision». Calculamos las frecuencias y los porcentajes de la variable «BIN_PD» en la base del modelo. También obtenemos el total de observaciones, almacenando el número en la macro variable «TOT_RECUENTO_BASE».
/*Recuentos y Proporciones de la tabla base buketizada (BASE_BUCKETIZADA)*/
/*Obtenemos las frecuencias de los distintos valores de la variable BIN_PD (categorías variable PD)*/
PROC SQL;
CREATE TABLE BASE_AUX AS SELECT
BIN_PD,
COUNT(*) AS RECUENTO_BASE
FROM BASE_BUCKETIZADA
GROUP BY BIN_PD;
QUIT;
/*Sumamos todas las frecuencias de cada categoría para obtener el total de observaciones*/
PROC SQL NOPRINT;
SELECT SUM(RECUENTO_BASE) INTO :TOT_RECUENTO_BASE
FROM BASE_AUX;
QUIT;
/*Calculamos la proporción de cada categoría*/
DATA BASE;
SET BASE_AUX;
PROPORCION_BASE = (RECUENTO_BASE/&TOT_RECUENTO_BASE);
RUN;
/*Sumamos todas las proporciones de cada categoría. Esta suma tiene que ser igual a 1*/
PROC SQL NOPRINT;
SELECT SUM(PROPORCION_BASE) INTO :TOT_PROPORCION_BASE
FROM BASE;
QUIT;
SAS👇🏻¿Dudas con alguna parte del código?
- PROC SQL;
- Inicia un procedimiento SQL en SAS para realizar consultas y manipulaciones de datos.
- CREATE TABLE BASE_AUX AS SELECT
CREATE TABLE BASE_AUX
: Crea una nueva tabla llamadaBASE_AUX
.AS SELECT
: Indica que la estructura y contenido deBASE_AUX
se basará en el resultado de la consultaSELECT
que sigue.
- BIN_PD, COUNT(*) AS RECUENTO_BASE
BIN_PD
: Columna seleccionada del conjunto de datosBASE_BUCKETIZADA
.COUNT(*)
: Función de agregación que cuenta todas las filas.AS RECUENTO_BASE
: Renombra el resultado deCOUNT(*)
aRECUENTO_BASE
.
- FROM BASE_BUCKETIZADA
- Especifica que los datos provienen del conjunto de datos
BASE_BUCKETIZADA
.
- Especifica que los datos provienen del conjunto de datos
- GROUP BY BIN_PD;
- Agrupa los datos por cada valor único en la columna
BIN_PD
.
- Agrupa los datos por cada valor único en la columna
- QUIT;
- Finaliza el bloque
PROC SQL
.
- Finaliza el bloque
- PROC SQL NOPRINT;
- Inicia otro bloque
PROC SQL
sin mostrar los resultados (output).
- Inicia otro bloque
- SELECT SUM(RECUENTO_BASE) INTO :TOT_RECUENTO_BASE FROM BASE_AUX;
SELECT SUM(RECUENTO_BASE)
: Calcula la suma total deRECUENTO_BASE
.INTO :TOT_RECUENTO_BASE
: Almacena el resultado en una macro variable llamadaTOT_RECUENTO_BASE
.FROM BASE_AUX
: Especifica que la suma se realiza sobre los datos deBASE_AUX
.
- DATA BASE;
- Crea un conjunto de datos llamado
BASE
.
- Crea un conjunto de datos llamado
- SET BASE_AUX;
- Lee y utiliza los datos del conjunto de datos
BASE_AUX
.
- Lee y utiliza los datos del conjunto de datos
- PROPORCION_BASE = (RECUENTO_BASE / &TOT_RECUENTO_BASE);
- Calcula la proporción de cada valor de
RECUENTO_BASE
con respecto al total enTOT_RECUENTO_BASE
.
- Calcula la proporción de cada valor de
- RUN;
- Ejecuta las instrucciones del bloque
DATA
.
- Ejecuta las instrucciones del bloque
- SELECT SUM(PROPORCION_BASE) INTO :TOT_PROPORCION_BASE FROM BASE;
- Calcula la suma de
PROPORCION_BASE
en el conjunto de datosBASE
y almacena el resultado en la macro variableTOT_PROPORCION_BASE
.
- Calcula la suma de
Una vez hemos calculado los valores que nos interesan, la tabla Base queda con la siguiente estructura:
Ahora tenemos segmentar los datos de la tabla actual en categorías basadas en los valores de «PD», utilizando los límites del procedimiento de bucketización:
/*Creamos la variable BIN_PD en la base Oot asignando los límites de cada categoría*/
DATA ACTUAL_BUCKETIZADA;
SET BBDD_OOT;
IF PD < 0.0001297533 THEN BIN_PD = 1;
ELSE IF 0.0001297533 <= PD < 0.0003390706 THEN BIN_PD = 2;
ELSE IF 0.0003390706 <= PD < 0.0006651284 THEN BIN_PD = 3;
ELSE IF 0.0006651284 <= PD < 0.0011938999 THEN BIN_PD = 4;
ELSE IF 0.0011938999 <= PD < 0.002089652 THEN BIN_PD = 5;
ELSE IF 0.002089652 <= PD < 0.0037419482 THEN BIN_PD = 6;
ELSE IF 0.0037419482 <= PD < 0.0074608021 THEN BIN_PD = 7;
ELSE IF 0.0074608021 <= PD < 0.0180660947 THEN BIN_PD = 8;
ELSE IF 0.0180660947 <= PD < 0.0641020781 THEN BIN_PD = 9;
ELSE BIN_PD = 10;
RUN;
SAS👇🏻¿Dudas con alguna parte del código?
- DATA ACTUAL_BUCKETIZADA;
- Crea o reemplaza un conjunto de datos llamado
ACTUAL_BUCKETIZADA
.
- Crea o reemplaza un conjunto de datos llamado
- SET BBDD_OOT;
- Lee y utiliza los datos del conjunto de datos
BBDD_OOT
. Este es el conjunto de datos de origen del que se tomará la variablePD
para su clasificación en buckets.
- Lee y utiliza los datos del conjunto de datos
- IF PD < 0.0001297533 THEN BIN_PD = 1; ELSE IF… ELSE BIN_PD = 10;
- Esta serie de instrucciones
IF...ELSE IF...ELSE
clasifica cada observación enBBDD_OOT
en una de las 10 categorías basadas en el valor de la variablePD
. - Cada condición especifica un rango para el valor de
PD
. Por ejemplo, siPD
es menor que 0.0001297533,BIN_PD
se establece en 1; siPD
está entre 0.0001297533 y 0.0003390706,BIN_PD
se establece en 2, y así sucesivamente. - La última condición
ELSE BIN_PD = 10;
captura todos los valores dePD
que no cumplen con ninguna de las condiciones anteriores, asignándoles el bucket 10.
- Esta serie de instrucciones
- RUN;
- Ejecuta el bloque de código
DATA
.
- Ejecuta el bloque de código
La tabla actual bucketizada nos queda así:
Obtenemos los recuentos y proporciones de «BIN_PD» en la tabla «ACTUAL_BUCKETIZADA»:
/*Recuentos y Proporciones de la tabla actual buketizada (ACTUAL_BUCKETIZADA)*/
/*Obtenemos las frecuencias de los distintos valores de la variable BIN_PD (categorías variable PD)*/
PROC SQL;
CREATE TABLE ACTUAL_AUX AS SELECT
BIN_PD,
COUNT(*) AS RECUENTO_ACTUAL
FROM ACTUAL_BUCKETIZADA
GROUP BY BIN_PD;
QUIT;
/*Sumamos todas las frecuencias de cada categoría para obtener el total de observaciones*/
PROC SQL NOPRINT;
SELECT SUM(RECUENTO_ACTUAL) INTO :TOT_RECUENTO_ACTUAL
FROM ACTUAL_AUX;
QUIT;
/*Calculamos la proporción de cada categoría*/
DATA ACTUAL;
SET ACTUAL_AUX;
PROPORCION_ACTUAL = (RECUENTO_ACTUAL/&TOT_RECUENTO_ACTUAL);
RUN;
/*Sumamos todas las proporciones de cada categoría. Esta suma tiene que ser igual a 1*/
PROC SQL NOPRINT;
SELECT SUM(PROPORCION_ACTUAL) INTO :TOT_PROPORCION_ACTUAL
FROM ACTUAL;
QUIT;
SAS👇🏻¿Dudas con alguna parte del código?
- PROC SQL;
- Inicia un procedimiento SQL en SAS para realizar consultas y manipulaciones de datos.
- CREATE TABLE ACTUAL_AUX AS SELECT
CREATE TABLE ACTUAL_AUX
: Crea una nueva tabla llamadaACTUAL_AUX
.AS SELECT
: Indica que la estructura y contenido deACTUAL_AUX
se basará en el resultado de la consultaSELECT
que sigue.
- BIN_PD, COUNT(*) AS RECUENTO_ACTUAL
BIN_PD
: Columna seleccionada del conjunto de datosACTUAL_BUCKETIZADA
.COUNT(*)
: Función de agregación que cuenta todas las filas.AS RECUENTO_ACTUAL
: Renombra el resultado deCOUNT(*)
aRECUENTO_ACTUAL
.
- FROM ACTUAL_BUCKETIZADA
- Especifica que los datos provienen del conjunto de datos
BBDD_OOT
.
- Especifica que los datos provienen del conjunto de datos
- GROUP BY BIN_PD;
- Agrupa los datos por cada valor único en la columna
BIN_PD
.
- Agrupa los datos por cada valor único en la columna
- QUIT;
- Finaliza el bloque
PROC SQL
.
- Finaliza el bloque
- PROC SQL NOPRINT;
- Inicia otro bloque
PROC SQL
sin mostrar los resultados (output).
- Inicia otro bloque
- SELECT SUM(RECUENTO_ACTUAL) INTO :TOT_RECUENTO_ACTUAL FROM ACTUAL_AUX;
SELECT SUM(RECUENTO_ACTUAL)
: Calcula la suma total deRECUENTO_ACTUAL
.INTO :TOT_RECUENTO_ACTUAL
: Almacena el resultado en una macro variable llamadaTOT_RECUENTO_ACTUAL
.FROM ACTUAL_AUX
: Especifica que la suma se realiza sobre los datos deACTUAL_AUX
.
- DATA ACTUAL;
- Crea un conjunto de datos llamado
ACTUAL
.
- Crea un conjunto de datos llamado
- SET ACTUAL_AUX;
- Lee y utiliza los datos del conjunto de datos
ACTUAL_AUX
.
- Lee y utiliza los datos del conjunto de datos
- PROPORCION_ACTUAL = (RECUENTO_ACTUAL / &TOT_RECUENTO_ACTUAL);
- Calcula la proporción de cada valor de
RECUENTO_ACTUAL
con respecto al total enTOT_RECUENTO_ACTUAL
.
- Calcula la proporción de cada valor de
- RUN;
- Ejecuta las instrucciones del bloque
DATA
.
- Ejecuta las instrucciones del bloque
- SELECT SUM(PROPORCION_ACTUAL) INTO :TOT_PROPORCION_ACTUAL FROM ACTUAL;
- Calcula la suma de
PROPORCION_ACTUAL
en el conjunto de datosACTUAL
y almacena el resultado en la macro variableTOT_PROPORCION_ACTUAL
.
- Calcula la suma de
La tabla Actual queda de la siguiente manera:
Cálculo del PSI
Realizamos el cálculo del PSI y creamos la variable «PD_BUCKET» que tomará los valores de la variable «BIN_PD» pero en formato de texto, porque queremos que el último registro sea un texto y tome el valor «TOTAL«.
/*Cálculo del PSI*/
DATA RESUMEN;
MERGE BASE ACTUAL;
BY BIN_PD;
IF RECUENTO_BASE = . THEN RECUENTO_BASE = 0;
IF RECUENTO_ACTUAL = . THEN RECUENTO_ACTUAL = 0;
IF RECUENTO_BASE = 0 THEN PROPORCION_BASE = (1/&TOT_RECUENTO_BASE);
IF RECUENTO_ACTUAL = 0 THEN PROPORCION_ACTUAL = (1/&TOT_RECUENTO_ACTUAL);
PSI = (PROPORCION_ACTUAL-PROPORCION_BASE)*LOG(PROPORCION_ACTUAL/PROPORCION_BASE);
PD_BUCKET=PUT(BIN_PD, 5.);
RUN;
SAS👇🏻¿Dudas con alguna parte del código?
- DATA RESUMEN;
- Crea o reemplaza un conjunto de datos llamado
RESUMEN
.
- Crea o reemplaza un conjunto de datos llamado
- MERGE BASE ACTUAL;
- Combina los conjuntos de datos
BASE
yACTUAL
. La fusión se realiza de forma que las filas de ambos conjuntos se alineen y se combinen en base a la variable especificada en la cláusulaBY
.
- Combina los conjuntos de datos
- BY BIN_PD;
- La fusión de los datos se realiza en base a la variable
BIN_PD
. Esto significa que los datos enBASE
yACTUAL
se compararán y combinarán según los valores de esta variable.
- La fusión de los datos se realiza en base a la variable
- IF RECUENTO_BASE = . THEN RECUENTO_BASE = 0;
- Reemplaza los valores faltantes (.) en
RECUENTO_BASE
con 0. Esto asegura que no haya valores faltantes que puedan afectar los cálculos siguientes.
- Reemplaza los valores faltantes (.) en
- IF RECUENTO_ACTUAL = . THEN RECUENTO_ACTUAL = 0;
- Similar a la línea anterior, pero para
RECUENTO_ACTUAL
.
- Similar a la línea anterior, pero para
- IF RECUENTO_BASE = 0 THEN PROPORCION_BASE = (1/&TOT_RECUENTO_BASE);
- Si
RECUENTO_BASE
es 0, asigna aPROPORCION_BASE
un valor mínimo basado en el total de recuentos de la base. Esto evita divisiones por cero o valores indefinidos en cálculos posteriores.
- Si
- IF RECUENTO_ACTUAL = 0 THEN PROPORCION_ACTUAL = (1/&TOT_RECUENTO_ACTUAL);
- Similar a la línea anterior, pero para
PROPORCION_ACTUAL
.
- Similar a la línea anterior, pero para
- PSI = (PROPORCION_ACTUAL – PROPORCION_BASE) * LOG(PROPORCION_ACTUAL / PROPORCION_BASE );
- Calcula el PSI para cada bucket. La fórmula mide la divergencia en las proporciones entre la población base y la actual, indicando cambios en la distribución.
- PD_BUCKET=PUT(BIN_PD, 5.);
- Convierte la variable
BIN_PD
a un formato de texto con un ancho de 5 caracteres. La funciónPUT()
se utiliza en SAS para convertir variables numéricas a formato de cadena de texto.
- Convierte la variable
- RUN;
- Ejecuta el bloque de código
DATA
.
- Ejecuta el bloque de código
La tabla que resulta del código se muestra a continuación:
Sumamos los PSIs de cada categoría y almacenamos el resultado en la macro variable PSI.
/*Guardamos el valor del PSI en la macro variable PSI*/
PROC SQL NOPRINT;
SELECT SUM(PSI) INTO :PSI
FROM RESUMEN;
QUIT;
SAS👇🏻¿Dudas con alguna parte del código?
- PROC SQL NOPRINT;
PROC SQL
: Inicia un procedimiento SQL, que permite ejecutar consultas y comandos SQL dentro de SAS.NOPRINT
: Esta opción evita que los resultados de la consulta SQL se muestren en la salida. Se usa cuando solo se necesita realizar una acción (como crear o actualizar una macro variable) sin necesidad de visualizar los resultados.
- SELECT SUM(PSI) INTO :PSI FROM RESUMEN;
SELECT SUM(PSI)
: Calcula la suma total de la columnaPSI
en el conjunto de datosRESUMEN
. El PSI, calculado previamente en cada fila, representa el índice de estabilidad para cada categoría definida porBIN_PD
.INTO :PSI
: Almacena el resultado de la suma en una macro variable llamadaPSI
. Las macro variables en SAS son útiles para almacenar valores que pueden ser utilizados en otras partes del programa SAS. El prefijo:
antes dePSI
indica que se trata de una macro variable.FROM RESUMEN
: Especifica que la suma del PSI se realiza sobre los datos del conjuntoRESUMEN
.
- QUIT;
- Finaliza el bloque
PROC SQL
.
- Finaliza el bloque
Creamos la tabla de Totales.
/*Se crea la fila de totales*/
DATA TOTALES;
PD_BUCKET = "TOTAL";
PSI = &PSI;
RECUENTO_BASE = &TOT_RECUENTO_BASE;
RECUENTO_ACTUAL = &TOT_RECUENTO_ACTUAL;
PROPORCION_BASE = &TOT_PROPORCION_BASE;
PROPORCION_ACTUAL = &TOT_PROPORCION_ACTUAL;
IF PSI <= 0.1 THEN RAG = "G";
ELSE IF 0.1 < PSI <= 0.25 THEN RAG = "A";
ELSE IF PSI > 0.25 THEN RAG = "R";
RUN;
SAS👇🏻¿Dudas con alguna parte del código?
- DATA TOTALES;
- Crea o reemplaza un conjunto de datos llamado
TOTALES
.
- Crea o reemplaza un conjunto de datos llamado
- PD_BUCKET = «TOTAL»;
- Asigna el valor «TOTAL» a la variable
PD_BUCKET
. Esto indica que la fila enTOTALES
es un resumen o representación agregada de todos los datos.
- Asigna el valor «TOTAL» a la variable
- PSI = &PSI;
- Asigna a la variable
PSI
el valor almacenado en la macro variablePSI
. Esta macro variable contiene el valor total del PSI calculado previamente.
- Asigna a la variable
- RECUENTO_BASE = &TOT_RECUENTO_BASE;
- Asigna a
RECUENTO_BASE
el valor almacenado en la macro variableTOT_RECUENTO_BASE
. Esta variable representa el recuento total en la base de datos original.
- Asigna a
- RECUENTO_ACTUAL = &TOT_RECUENTO_ACTUAL;
- Asigna a
RECUENTO_ACTUAL
el valor almacenado en la macro variableTOT_RECUENTO_ACTUAL
. Similar aRECUENTO_BASE
, representa el recuento total en los datos actuales.
- Asigna a
- PROPORCION_BASE = &TOT_PROPORCION_BASE;
- Asigna a
PROPORCION_BASE
el valor de la macro variableTOT_PROPORCION_BASE
, que es la proporción total en la base de datos original.
- Asigna a
- PROPORCION_ACTUAL = &TOT_PROPORCION_ACTUAL;
- Asigna a
PROPORCION_ACTUAL
el valor de la macro variableTOT_PROPORCION_ACTUAL
, que es la proporción total en los datos actuales.
- Asigna a
- IF PSI <= 0.1 THEN RAG = «G»; ELSE IF 0.1 < PSI <= 0.25 THEN RAG = «A»; ELSE IF PSI > 0.25 THEN RAG = «R»;
- Esta serie de instrucciones condicionales clasifica el valor del PSI en categorías RAG (Rojo, Ámbar, Verde) según su valor. Si el PSI es menor o igual a 0.1, se clasifica como «G» (verde, indicando estabilidad); si está entre 0.1 y 0.25, se clasifica como «A» (ámbar, indicando una advertencia); si es mayor que 0.25, se clasifica como «R» (rojo, indicando inestabilidad).
- RUN;
- Ejecuta el bloque de código
DATA
.
- Ejecuta el bloque de código
La tabla resultante es la siguiente:
Por último, unimos las tablas Resumen y Totales en una única tabla llamada Resultado. Ordenamos las columnas en el orden deseado con la palabra clave «RETAIN» y le ponemos 4 decimales a las proporciones.
/*Añadimos los totales a la tabla resumen*/
DATA RESULTADO (DROP= BIN_PD);
RETAIN PD_BUCKET RECUENTO_BASE RECUENTO_ACTUAL PROPORCION_BASE PROPORCION_ACTUAL PSI RAG;
SET RESUMEN TOTALES;
FORMAT PROPORCION_BASE 6.4;
FORMAT PROPORCION_ACTUAL 6.4;
RUN;
SAS👇🏻¿Dudas con alguna parte del código?
- DATA RESULTADO (DROP= BIN_PD);
- Crea o reemplaza un conjunto de datos llamado
RESULTADO
. - La opción
DROP= BIN_PD
excluye la variableBIN_PD
del conjunto de datos resultante,RESULTADO
. Esto significa que aunqueBIN_PD
pueda estar presente en los conjuntos de datos originales (RESUMEN
oTOTALES
), no se incluirá enRESULTADO
.
- Crea o reemplaza un conjunto de datos llamado
- RETAIN PD_BUCKET RECUENTO_BASE RECUENTO_ACTUAL PROPORCION_BASE PROPORCION_ACTUAL PSI RAG;
- La instrucción
RETAIN
especifica el orden en que las variables aparecerán en el conjunto de datos resultante. Además,RETAIN
también asegura que los valores de estas variables se mantengan a través de las iteraciones del pasoDATA
.
- La instrucción
- SET RESUMEN TOTALES;
- La instrucción
SET
se utiliza para apilar o combinar los registros de los conjuntos de datosRESUMEN
yTOTALES
en el nuevo conjunto de datosRESULTADO
. La combinación se realiza apilando los registros deTOTALES
debajo de los registros deRESUMEN
.
- La instrucción
- FORMAT PROPORCION_BASE 6.4; FORMAT PROPORCION_ACTUAL 6.4;
- Estas líneas aplican un formato específico a las variables
PROPORCION_BASE
yPROPORCION_ACTUAL
. El formato6.4
significa que estas variables se mostrarán con un total de 6 dígitos, incluyendo 4 dígitos después del punto decimal. Por ejemplo, un número como 0.1234 se mostrará en este formato.
- Estas líneas aplican un formato específico a las variables
- RUN;
- Ejecuta el bloque de código
DATA
.
- Ejecuta el bloque de código
El resultado final es el siguiente:
Conclusión
El PSI de la variable «PD» es:
\text{PSI} = 0,03677 + ... + 0,00039 = 0,06738
Al evaluar la variable continua «PD» hemos obtenido un PSI de 0,06738. Este resultado se compone de pequeñas contribuciones en cada uno de los deciles, siendo la mayor en el primer rango.
Un PSI total de aproximadamente 0,067 indica que no ha habido cambios sustanciales en la distribución de la probabilidad de incumplimiento desde que se desarrolló el modelo. Un valor de PSI inferior a 0,1 generalmente se considera como indicativo de estabilidad, lo que sugiere que el modelo predictivo actual sigue siendo adecuado y no se necesitarían acciones inmediatas en términos de recalibración o desarrollo de un nuevo modelo basándonos exclusivamente en esta variable.
Por lo tanto, en base a la variable «PD», podemos concluir que el modelo predictivo mantiene su capacidad para estimar la probabilidad de incumplimiento de forma consistente con cómo fue diseñado originalmente. Esto implica que, al menos en lo que respecta a esta métrica específica, el modelo sigue siendo robusto y no muestra signos de degradación significativa que justifiquen una intervención urgente.
Conclusión
Tras evaluar las variables «Motor de decisión» y «PD» con el Índice de Estabilidad de la Población (PSI), hemos llegado a conclusiones distintas para cada una. Para «Motor de decisión», un PSI de 0,77 sugiere que ha habido cambios muy significativos en la distribución desde la creación del modelo, lo que podría señalar la necesidad de una actualización o revisión más detallada. Por otro lado, un PSI de 0,067 para «PD» indica una estabilidad en la distribución de la probabilidad de incumplimiento , lo que implica que esta variable no ha experimentado cambios que afecten la fiabilidad del modelo.
En términos generales, la combinación de estos resultados señala que, mientras la variable «PD» se mantiene estable y el modelo predictivo es todavía confiable en este aspecto, la variable «Motor de decisión» muestra un cambio considerable, especialmente destacado por la aparición de la categoría «3.Joven» en la base actual, la cual no existía en los datos de desarrollo. Este cambio sustancial, evidenciado por un PSI elevado para esta categoría, sugiere una dinámica de mercado emergente o un cambio en la demografía de los clientes que no se refleja en el modelo original.
Por lo tanto, se recomienda una revisión exhaustiva del modelo, considerando particularmente las implicaciones de la inclusión de la nueva categoría «3.Joven», para garantizar que el modelo sigue siendo relevante y refleja las condiciones actuales del mercado y comportamiento del cliente.
Bibliografía
Population Stability Index (PSI)
STATISTICAL PROPERTIES OF POPULATION STABILITY INDEX by Bilal Yurdakul
Un comentario