Basic exploration of the dataset
In [3]: import pandas as pd
import numpy as np
import [Link] as plt
import seaborn as sns
%matplotlib inline
# Cargando el dataset; si hay problemas de tipos, usar low_memory=False
df = pd.read_csv('accepted_2007_to_2018Q4.csv', low_memory=False)
# Mostrando las primeras filas del dataset
[Link]()
Out[3]: member_id loan_amnt funded_amnt funded_amnt_inv int_rate installment annual_inc dti delinq_2yrs fico_range_low ... deferral_term hardship_amount hardship_length hardship_dpd orig_projected_additional_accrued_interest hardship_payoff_bal
count 0.0 2.260668e+06 2.260668e+06 2.260668e+06 2.260668e+06 2.260668e+06 2.260664e+06 2.258957e+06 2.260639e+06 2.260668e+06 ... 10917.0 10917.000000 10917.0 10917.000000 8651.000000 1
mean NaN 1.504693e+04 1.504166e+04 1.502344e+04 1.309283e+01 4.458068e+02 7.799243e+04 1.882420e+01 3.068792e-01 6.985882e+02 ... 3.0 155.045981 3.0 13.743886 454.798089 1
std NaN 9.190245e+03 9.188413e+03 9.192332e+03 4.832138e+00 2.671735e+02 1.126962e+05 1.418333e+01 8.672303e-01 3.301038e+01 ... 0.0 129.040594 0.0 9.671178 375.385500
min NaN 5.000000e+02 5.000000e+02 0.000000e+00 5.310000e+00 4.930000e+00 0.000000e+00 -1.000000e+00 0.000000e+00 6.100000e+02 ... 3.0 0.640000 3.0 0.000000 1.920000
25% NaN 8.000000e+03 8.000000e+03 8.000000e+03 9.490000e+00 2.516500e+02 4.600000e+04 1.189000e+01 0.000000e+00 6.750000e+02 ... 3.0 59.440000 3.0 5.000000 175.230000
50% NaN 1.290000e+04 1.287500e+04 1.280000e+04 1.262000e+01 3.779900e+02 6.500000e+04 1.784000e+01 0.000000e+00 6.900000e+02 ... 3.0 119.140000 3.0 15.000000 352.770000 1
75% NaN 2.000000e+04 2.000000e+04 2.000000e+04 1.599000e+01 5.933200e+02 9.300000e+04 2.449000e+01 0.000000e+00 7.150000e+02 ... 3.0 213.260000 3.0 22.000000 620.175000 1
max NaN 4.000000e+04 4.000000e+04 4.000000e+04 3.099000e+01 1.719830e+03 1.100000e+08 9.990000e+02 5.800000e+01 8.450000e+02 ... 3.0 943.940000 3.0 37.000000 2680.890000 4
8 rows × 113 columns
Proporción de Pagos Completos vs Impagos
Se asume que existe una columna que indique el estado del préstamo, por ejemplo, loan_status (o similar). Calcula la proporción usando value_counts(normalize=True):
In [4]: # Mostrar proporciones de estados del préstamo
proporcion_status = df['loan_status'].value_counts(normalize=True)
proporcion_status
Out[4]: loan_status
Fully Paid 0.476298
Current 0.388521
Charged Off 0.118796
Late (31-120 days) 0.009496
In Grace Period 0.003732
Late (16-30 days) 0.001924
Does not meet the credit policy. Status:Fully Paid 0.000879
Does not meet the credit policy. Status:Charged Off 0.000337
Default 0.000018
Name: proportion, dtype: float64
Hipótesis para Explicar la Calificación (Grade)
Ejemplo de Hipótesis: “Los préstamos con calificación alta (ej. A, B) tienen menores tasas de incumplimiento y se otorgan a solicitantes con mejores ingresos y menor nivel de endeudamiento, mientras que aquellos con calificación baja (ej. D, E) presentan mayor riesgo, tasas de
interés más altas y características crediticias más débiles.”
Implementación:
Analiza la relación entre grade y loan_status.
Compara también variables como annual_inc, dti y int_rate según el grade.
In [5]: # Conteo de préstamos por grade y estado
tabla_grade_status = [Link](df['grade'], df['loan_status'])
print(tabla_grade_status)
# Estadísticas de ingresos y tasas de interés por grade
stats_grade = [Link]('grade')[['annual_inc', 'int_rate']].agg(['mean', 'std', 'min', 'max'])
print(stats_grade)
loan_status Charged Off Current Default \
grade
A 14201 195539 5
B 52569 262903 7
C 85649 255707 8
D 61054 115138 13
E 36035 38080 6
F 14491 8485 1
G 4560 2465 0
loan_status Does not meet the credit policy. Status:Charged Off \
grade
A 8
B 85
C 148
D 197
E 158
F 93
G 72
loan_status Does not meet the credit policy. Status:Fully Paid Fully Paid \
grade
A 90 220889
B 269 340172
C 481 296037
D 494 139899
E 378 57615
F 154 17567
G 122 4572
loan_status In Grace Period Late (16-30 days) Late (31-120 days)
grade
A 632 341 1322
B 1771 993 4788
C 2993 1476 7554
D 1899 969 4761
E 799 402 2166
F 240 129 640
G 102 39 236
annual_inc int_rate \
mean std min max mean std
grade
A 89902.403133 90257.586254 0.0 9573072.0 7.084545 0.984465
B 78813.567867 171206.834156 0.0 110000000.0 10.675806 1.238302
C 74370.290585 72636.156459 0.0 9930475.0 14.143689 1.251283
D 71030.182415 68770.876079 0.0 10999200.0 18.143067 1.676964
E 71855.514982 63392.866932 0.0 8500000.0 21.829653 2.703925
F 72657.784855 49037.104820 0.0 2500000.0 25.454091 2.928144
G 75241.685705 51027.563924 0.0 980000.0 28.074255 2.804587
min max
grade
A 5.31 9.63
B 6.00 14.09
C 6.00 17.27
D 6.00 22.35
E 6.00 27.27
F 6.00 30.75
G 6.00 30.99
Relación de la Calificación (Grade) con Pagos y Destino
Aquí se explora cómo varía el estado del préstamo y el propósito (purpose) según el grade:
Pagos: Visualiza el porcentaje de “fully paid” vs “default” para cada grade.
Destino: Utiliza gráficos de barras para ver la distribución de purpose en cada grade.
In [6]: # Porcentaje de estados por grade
grade_status = [Link](df['grade'], df['loan_status'], normalize='index') * 100
grade_status.plot(kind='bar', stacked=True, figsize=(10,6))
[Link]('Proporción de Estados de Préstamo por Grade')
[Link]('Grade')
[Link]('Porcentaje')
[Link](title='Loan Status')
[Link]()
# Distribución de propósito por grade (usando countplot)
[Link](figsize=(12,6))
[Link](x='grade', hue='purpose', data=df)
[Link]('Distribución del Propósito según Grade')
[Link]('Grade')
[Link]('Cantidad de Préstamos')
[Link](bbox_to_anchor=(1.05, 1), loc='upper left')
[Link]()
Relación de la Sub-Calificación (Sub-Grade)
Realiza un análisis similar al anterior pero a nivel de sub_grade para ver diferencias más finas:
In [18]: # Asegurar que 'sub_grade' sea tipo string y ordenar sin valores nulos
df['sub_grade'] = df['sub_grade'].astype(str)
sub_grade_order = sorted(df['sub_grade'].dropna().unique(), key=str)
# Conteo de préstamos por sub_grade
[Link](figsize=(12,6))
[Link](x='sub_grade', data=df, order=sub_grade_order)
[Link]('Cantidad de Préstamos por Sub-Grade')
[Link]('Sub-Grade')
[Link]('Cantidad')
[Link]()
# Boxplot de tasa de interés por sub_grade
[Link](figsize=(12,6))
[Link](x='sub_grade', y='int_rate', data=df, order=sub_grade_order)
[Link]('Tasa de Interés según Sub-Grade')
[Link]('Sub-Grade')
[Link]('Tasa de Interés')
[Link]()
Créditos por Categoría y Variación del Monto del Préstamo
Asumiendo que “categoría” se refiere a la columna grade o alguna otra (por ejemplo, loan_category), puedes agrupar y contar los créditos, y analizar cómo varía loan_amnt:
In [8]: # Créditos por grade (o categoría)
creditos_por_grade = df['grade'].value_counts().sort_index()
print(creditos_por_grade)
# Variación del monto del préstamo dentro de cada grade
monto_por_grade = [Link]('grade')['loan_amnt'].describe()
print(monto_por_grade)
# Boxplot del monto del préstamo por grade
[Link](figsize=(10,6))
[Link](x='grade', y='loan_amnt', data=df)
[Link]('Distribución del Monto del Préstamo por Grade')
[Link]('Grade')
[Link]('Monto del Préstamo')
[Link]()
grade
A 433027
B 663557
C 650053
D 324424
E 135639
F 41800
G 12168
Name: count, dtype: int64
count mean std min 25% 50% \
grade
A 433027.0 14603.343210 9107.975657 500.0 8000.00 12000.0
B 663557.0 14173.338199 8957.012601 500.0 7400.00 12000.0
C 650053.0 15038.083318 9203.950054 500.0 8000.00 13000.0
D 324424.0 15711.983007 9250.612823 500.0 8575.00 14400.0
E 135639.0 17453.078392 9363.276694 600.0 10000.00 16000.0
F 41800.0 19124.646531 9166.366254 1000.0 12000.00 18175.0
G 12168.0 20383.988741 8994.472986 600.0 13193.75 19800.0
75% max
grade
A 20000.00 40000.0
B 20000.00 40000.0
C 20000.00 40000.0
D 21200.00 40000.0
E 24175.00 40000.0
F 25600.00 40000.0
G 27656.25 40000.0
<Figure size 1200x600 with 0 Axes>
Tasa de Interés según Categoría y Subcategoría
Agrupa los datos por grade y sub_grade para analizar la tasa de interés. Calcula estadísticas descriptivas (promedio, desviación estándar, mínimo y máximo):
In [9]: # Estadísticas de int_rate por grade y sub_grade
stats_int_rate = [Link](['grade', 'sub_grade'])['int_rate'].agg(['mean', 'std', 'min', 'max']).reset_index()
print(stats_int_rate)
grade sub_grade mean std min max
0 A A1 5.600265 0.392642 5.31 7.37
1 A A2 6.552337 0.350171 5.79 7.68
2 A A3 7.094535 0.304612 6.00 8.00
3 A A4 7.560239 0.328957 6.00 9.32
4 A A5 8.195006 0.376874 6.00 9.63
5 B B1 9.078554 0.711623 6.00 11.49
6 B B2 9.974970 0.634192 6.00 11.48
7 B B3 10.705015 0.738832 6.00 12.12
8 B B4 11.372778 0.679236 6.00 13.11
9 B B5 12.013545 0.684719 6.00 14.09
10 C C1 12.783783 0.619874 6.00 14.33
11 C C2 13.537632 0.700316 6.00 15.31
12 C C3 14.104219 0.674943 6.00 15.80
13 C C4 14.878059 0.741572 6.00 16.29
14 C C5 15.768243 0.795525 6.00 17.27
15 D D1 16.658169 0.903537 6.00 17.97
16 D D2 17.599961 0.984731 6.00 18.94
17 D D3 18.388456 1.155439 6.00 19.92
18 D D4 19.072871 1.353237 6.00 20.89
19 D D5 20.063591 1.779733 6.00 22.35
20 E E1 20.333383 2.047001 6.00 23.40
21 E E2 21.013473 2.314130 6.00 24.37
22 E E3 21.881358 2.497842 6.00 25.34
23 E E4 22.778776 2.534248 6.00 26.31
24 E E5 24.108853 2.524670 6.00 27.27
25 F F1 24.547291 2.827584 6.00 28.72
26 F F2 24.986190 2.799307 6.00 29.69
27 F F3 25.778108 2.738459 6.00 30.17
28 F F4 26.347711 2.785019 6.00 30.65
29 F F5 27.102973 2.765629 6.00 30.75
30 G G1 27.850828 2.731967 6.00 30.79
31 G G2 27.653650 2.649962 6.00 30.84
32 G G3 28.106609 2.706446 6.00 30.89
33 G G4 28.557985 2.946767 6.00 30.94
34 G G5 28.809005 2.997214 6.00 30.99
Destino del Crédito (Purpose) y Relación con Monto, Cantidad y Plazos
Explora la columna purpose para ver la cantidad de préstamos, los montos y los plazos asociados (posiblemente term):
In [10]: # Créditos asignados por propósito
creditos_por_purpose = df['purpose'].value_counts()
print(creditos_por_purpose)
# Estadísticas de monto del préstamo por propósito
monto_por_purpose = [Link]('purpose')['loan_amnt'].agg(['mean', 'std', 'min', 'max'])
print(monto_por_purpose)
# Visualizar con boxplot el monto del préstamo por propósito
[Link](figsize=(12,6))
[Link](x='purpose', y='loan_amnt', data=df)
[Link]('Monto del Préstamo según Propósito')
[Link]('Propósito')
[Link]('Monto del Préstamo')
[Link](rotation=45)
[Link]()
# Si tienes columna de plazo (por ejemplo, "term"), analiza también:
if 'term' in [Link]:
[Link](figsize=(12,6))
[Link](x='purpose', y='term', data=df)
[Link]('Plazo del Préstamo según Propósito')
[Link]('Propósito')
[Link]('Plazo')
[Link](rotation=45)
[Link]()
# Relacionar incumplimiento: Por ejemplo, ver la tasa de default por propósito
default_por_purpose = [Link](df['purpose'], df['loan_status'], normalize='index') * 100
print(default_por_purpose)
purpose
debt_consolidation 1277877
credit_card 516971
home_improvement 150457
other 139440
major_purchase 50445
medical 27488
small_business 24689
car 24013
vacation 15525
moving 15403
house 14136
wedding 2355
renewable_energy 1445
educational 424
Name: count, dtype: int64
mean std min max
purpose
car 9393.720068 6841.440776 1000.0 40000.0
credit_card 15319.730362 8871.968072 500.0 40000.0
debt_consolidation 15966.695954 9044.201289 700.0 40000.0
educational 6614.622642 5087.953508 500.0 25000.0
home_improvement 14666.147969 9739.678116 900.0 40000.0
house 15703.917303 10186.178199 1000.0 40000.0
major_purchase 12682.430370 9811.653704 1000.0 40000.0
medical 9474.190556 7673.478159 500.0 40000.0
moving 8390.811855 7162.695848 800.0 40000.0
other 10481.091150 8595.613327 500.0 40000.0
renewable_energy 10757.024221 8732.538967 1000.0 40000.0
small_business 16442.694115 10245.608646 500.0 40000.0
vacation 6357.995169 5688.961619 500.0 40000.0
wedding 10475.859873 6750.017705 1000.0 35000.0
loan_status Charged Off Current Default \
purpose
car 8.916004 37.746221 0.012493
credit_card 9.668241 41.557457 0.001161
debt_consolidation 12.913136 37.283714 0.001643
educational 13.207547 0.235849 0.000000
home_improvement 10.303276 40.152336 0.001994
house 11.226655 46.321449 0.007074
major_purchase 10.849440 39.710576 0.003965
medical 12.321740 41.563591 0.007276
moving 14.373823 36.337077 0.000000
other 11.750574 42.064687 0.001434
renewable_energy 15.294118 33.910035 0.000000
small_business 18.550772 34.796873 0.000000
vacation 11.194847 40.045089 0.000000
wedding 11.847134 0.212314 0.000000
loan_status Does not meet the credit policy. Status:Charged Off \
purpose
car 0.054137
credit_card 0.013347
debt_consolidation 0.022850
educational 7.547170
home_improvement 0.047190
house 0.077816
major_purchase 0.045594
medical 0.080035
moving 0.097384
other 0.086776
renewable_energy 0.069204
small_business 0.291628
vacation 0.038647
wedding 0.552017
loan_status Does not meet the credit policy. Status:Fully Paid \
purpose
car 0.212385
credit_card 0.052421
debt_consolidation 0.063230
educational 15.330189
home_improvement 0.095044
house 0.233447
major_purchase 0.198236
medical 0.130966
moving 0.201259
other 0.217298
renewable_energy 0.138408
small_business 0.360484
vacation 0.083736
wedding 1.825902
loan_status Fully Paid In Grace Period Late (16-30 days) \
purpose
car 51.821930 0.312331 0.124932
credit_card 47.448890 0.323422 0.158616
debt_consolidation 48.150722 0.391117 0.197359
educational 63.679245 0.000000 0.000000
home_improvement 47.855533 0.370870 0.216009
house 40.082060 0.431522 0.297114
major_purchase 47.481415 0.372683 0.212112
medical 44.262951 0.385623 0.178260
moving 47.172629 0.383042 0.279166
other 44.097820 0.408778 0.222318
renewable_energy 49.273356 0.069204 0.276817
small_business 43.889991 0.449593 0.287577
vacation 47.194847 0.238325 0.167472
wedding 85.562633 0.000000 0.000000
loan_status Late (31-120 days)
purpose
car 0.799567
credit_card 0.776446
debt_consolidation 0.976229
educational 0.000000
home_improvement 0.957749
house 1.322864
major_purchase 1.125979
medical 1.069558
moving 1.155619
other 1.150316
renewable_energy 0.968858
small_business 1.373081
vacation 1.037037
wedding 0.000000
Análisis de Créditos Completamente Pagados
Para los préstamos "fully paid", investiga la distribución del tiempo, cantidad de pagos, plazo real, fecha de asignación y fecha del último pago. Si existen columnas como issue_d (fecha de asignación), last_pymnt_d (fecha del último pago) y term:
In [19]: # Filtrar solo los préstamos completados y crear una copia explícita
df_paid = df[df['loan_status'] == 'Fully Paid'].copy()
# Convertir las columnas de fecha a datetime
df_paid['issue_d'] = pd.to_datetime(df_paid['issue_d'], errors='coerce')
df_paid['last_pymnt_d'] = pd.to_datetime(df_paid['last_pymnt_d'], errors='coerce')
# Visualizar distribución del plazo real (suponiendo que 'term' existe)
if 'term' in df_paid.columns:
[Link](figsize=(10,6))
[Link](x='grade', y='term', data=df_paid)
[Link]('Plazo Real (term) según Grade para Préstamos Completados')
[Link]('Grade')
[Link]('Term')
[Link]()
# Calcular duración real en meses y evitar el SettingWithCopyWarning usando .loc
df_paid.loc[:, 'duracion_meses'] = (df_paid['last_pymnt_d'] - df_paid['issue_d']).[Link] / 30
[Link](figsize=(10,6))
[Link](x='grade', y='duracion_meses', data=df_paid)
[Link]('Duración Real (meses) según Grade para Préstamos Completados')
[Link]('Grade')
[Link]('Duración (meses)')
[Link]()
C:\Users\[Link]\AppData\Local\Temp\ipykernel_42732\[Link]: UserWarning: Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, pleas
e specify a format.
df_paid['issue_d'] = pd.to_datetime(df_paid['issue_d'], errors='coerce')
C:\Users\[Link]\AppData\Local\Temp\ipykernel_42732\[Link]: UserWarning: Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, pleas
e specify a format.
df_paid['last_pymnt_d'] = pd.to_datetime(df_paid['last_pymnt_d'], errors='coerce')
Manejo de Datos Faltantes
Revisa la cantidad de datos faltantes y analiza su impacto:
In [12]: # Conteo de valores faltantes por columna
missing_values = [Link]().sum()
print(missing_values.sort_values(ascending=False).head(20))
member_id 2260701
orig_projected_additional_accrued_interest 2252050
hardship_end_date 2249784
hardship_start_date 2249784
hardship_type 2249784
hardship_reason 2249784
hardship_status 2249784
deferral_term 2249784
hardship_last_payment_amount 2249784
hardship_payoff_balance_amount 2249784
hardship_loan_status 2249784
hardship_dpd 2249784
hardship_length 2249784
payment_plan_start_date 2249784
hardship_amount 2249784
settlement_term 2226455
debt_settlement_flag_date 2226455
settlement_status 2226455
settlement_date 2226455
settlement_amount 2226455
dtype: int64
Casos en los que los Datos Faltantes son Normales en el Negocio
Por ejemplo, el atributo monthsSinceLastDelinquency puede ser nulo cuando el cliente nunca tuvo mora. En este caso, un valor nulo indica “sin mora” y podrías reemplazarlo por 0 o crear una variable booleana adicional.
In [16]: # Ejemplo de imputación para monthsSinceLastDelinquency
# Supongamos que 'months_since_last_delinquency' es el nombre de la columna
if 'months_since_last_delinquency' in [Link]:
df['months_since_last_delinquency_imputed'] = df['months_since_last_delinquency'].fillna(0)
Variables a Descartar del Modelo por Altos Niveles de Datos Faltantes
Revisa el porcentaje de faltantes en cada variable:
In [17]: # Porcentaje de faltantes por columna
missing_percent = ([Link]().sum() / len(df)) * 100
print(missing_percent.sort_values(ascending=False).head(10))
member_id 100.000000
orig_projected_additional_accrued_interest 99.617331
hardship_end_date 99.517097
hardship_start_date 99.517097
hardship_type 99.517097
hardship_reason 99.517097
hardship_status 99.517097
deferral_term 99.517097
hardship_last_payment_amount 99.517097
hardship_payoff_balance_amount 99.517097
dtype: float64
Variables a Descartar por Altos Niveles de Faltantes
Primero, analiza el porcentaje de datos faltantes por variable. Por ejemplo, si decides que las variables con más del 80% de datos faltantes no aportan información confiable, podrías descartarlas.
Nota:
Antes de decidir eliminar una variable, revisa si su ausencia es sistemática o si, a pesar de los faltantes, aporta información importante.
Eliminar variables con demasiados faltantes puede reducir ruido y complejidad en el modelo, pero también se corre el riesgo de perder información relevante.
Es importante documentar en el análisis que se asume que la variable descartada no aporta información única o que su mecanismo de ausencia es aleatorio.
In [20]: # Calcular el porcentaje de datos faltantes por columna
missing_percent = ([Link]().sum() / len(df)) * 100
missing_percent_sorted = missing_percent.sort_values(ascending=False)
print("Porcentaje de datos faltantes por variable:")
print(missing_percent_sorted.head(15)) # Muestra las 15 variables con mayor porcentaje de faltantes
# Definir un umbral: por ejemplo, variables con más del 80% de datos faltantes
umbral = 80
vars_to_drop = missing_percent[missing_percent > umbral].[Link]()
print("\nVariables a considerar para ser descartadas (más del 80% de faltantes):")
print(vars_to_drop)
Porcentaje de datos faltantes por variable:
member_id 100.000000
orig_projected_additional_accrued_interest 99.617331
hardship_end_date 99.517097
hardship_start_date 99.517097
hardship_type 99.517097
hardship_reason 99.517097
hardship_status 99.517097
deferral_term 99.517097
hardship_last_payment_amount 99.517097
hardship_payoff_balance_amount 99.517097
hardship_loan_status 99.517097
hardship_dpd 99.517097
hardship_length 99.517097
payment_plan_start_date 99.517097
hardship_amount 99.517097
dtype: float64
Variables a considerar para ser descartadas (más del 80% de faltantes):
['member_id', 'desc', 'mths_since_last_record', 'annual_inc_joint', 'dti_joint', 'verification_status_joint', 'revol_bal_joint', 'sec_app_fico_range_low', 'sec_app_fico_range_high', 'sec_app_earliest_cr_line', 'sec_app_inq_last_6mths',
'sec_app_mort_acc', 'sec_app_open_acc', 'sec_app_revol_util', 'sec_app_open_act_il', 'sec_app_num_rev_accts', 'sec_app_chargeoff_within_12_mths', 'sec_app_collections_12_mths_ex_med', 'sec_app_mths_since_last_major_derog', 'hardship_ty
pe', 'hardship_reason', 'hardship_status', 'deferral_term', 'hardship_amount', 'hardship_start_date', 'hardship_end_date', 'payment_plan_start_date', 'hardship_length', 'hardship_dpd', 'hardship_loan_status', 'orig_projected_additional
_accrued_interest', 'hardship_payoff_balance_amount', 'hardship_last_payment_amount', 'debt_settlement_flag_date', 'settlement_status', 'settlement_date', 'settlement_amount', 'settlement_percentage', 'settlement_term']
Datos Clave para Invertir en un Crédito
Para evaluar la viabilidad y rentabilidad de invertir en un crédito, es indispensable contar con la siguiente información:
Estado del préstamo (loan_status): Permite conocer si el préstamo se encuentra al día, completamente pagado o en incumplimiento.
Tasa de interés (int_rate): Es fundamental para determinar la rentabilidad y para evaluar el riesgo, ya que préstamos con mayores riesgos suelen tener tasas más altas.
Calificación crediticia (grade y sub_grade): Proporcionan una síntesis del riesgo asociado al préstamo.
Monto del préstamo (loan_amnt): Indica la cantidad de dinero involucrada, lo que influye en la exposición y en el retorno esperado.
Propósito del préstamo (purpose): Ayuda a entender el contexto y la finalidad del crédito, lo que puede influir en su riesgo y rentabilidad.
Ingresos anuales del solicitante (annual_inc): Permite evaluar la capacidad de pago y la estabilidad financiera del deudor.
Ratio deuda/ingreso (dti): Es un indicador crítico del nivel de endeudamiento y de la capacidad del solicitante para manejar nuevas obligaciones.
Historial crediticio: Variables como los rangos FICO (fico_range_low y fico_range_high) y el historial de morosidad (delinq_2yrs) son claves para entender el comportamiento crediticio previo.
Plazo del préstamo (term): Indica la duración del compromiso financiero y puede influir en el riesgo y en la estructura de pagos.
Fechas relevantes (issue_d, last_pymnt_d): Permiten analizar la evolución temporal del préstamo, lo que es útil para entender la dinámica de pagos y la duración real del crédito.
Esta información es esencial para construir modelos predictivos robustos y para tomar decisiones informadas en la inversión de créditos.