Spaces:
Running
Running
File size: 2,398 Bytes
42029e4 8c66d1b 42029e4 8c66d1b 42029e4 8c66d1b 42029e4 8c66d1b 42029e4 8c66d1b 42029e4 8c66d1b 42029e4 8c66d1b 42029e4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | from __future__ import annotations
import numpy as np
import pandas as pd
def _safe_qcut(series: pd.Series, q: int=10) -> pd.Series:
s = pd.to_numeric(series, errors='coerce')
try:
binned = pd.qcut(s, q=q, labels=False, duplicates='drop')
return binned.astype('Int64')
except (ValueError, IndexError):
return pd.Series([pd.NA] * len(s), index=s.index, dtype='Int64')
def build_behavioral_features(df: pd.DataFrame, today: pd.Timestamp | None=None) -> pd.DataFrame:
df = df.copy()
today = today or df.get('issue_d', pd.Series([pd.Timestamp.today()])).max()
if {'loan_amnt', 'annual_inc'}.issubset(df.columns):
df['loan_to_income'] = df['loan_amnt'] / df['annual_inc'].replace(0, np.nan)
if {'installment', 'annual_inc'}.issubset(df.columns):
df['installment_to_income'] = df['installment'] * 12 / df['annual_inc'].replace(0, np.nan)
if {'revol_bal', 'annual_inc'}.issubset(df.columns):
df['revol_bal_to_income'] = df['revol_bal'] / df['annual_inc'].replace(0, np.nan)
if {'earliest_cr_line', 'issue_d'}.issubset(df.columns):
df['credit_history_years'] = ((df['issue_d'] - df['earliest_cr_line']).dt.days / 365.25).clip(lower=0)
if {'open_acc', 'total_acc'}.issubset(df.columns):
df['pct_open_acc'] = df['open_acc'] / df['total_acc'].replace(0, np.nan)
neg_cols = [c for c in ('delinq_2yrs', 'pub_rec', 'pub_rec_bankruptcies') if c in df.columns]
if neg_cols:
df['n_negative_events'] = df[neg_cols].fillna(0).sum(axis=1)
if 'dti' in df.columns:
df['flag_high_dti'] = (df['dti'] > 35).astype(int)
if 'emp_length' in df.columns:
df['flag_no_employment'] = df['emp_length'].fillna(0).eq(0).astype(int)
if 'annual_inc' in df.columns:
df['income_bucket'] = _safe_qcut(df['annual_inc'], q=10)
if 'loan_amnt' in df.columns:
df['loan_bucket'] = _safe_qcut(df['loan_amnt'], q=10)
if 'issue_d' in df.columns:
df['app_month'] = df['issue_d'].dt.month
df['app_quarter'] = df['issue_d'].dt.quarter
df['app_year'] = df['issue_d'].dt.year
for col in ('title', 'emp_title'):
if col in df.columns:
s = df[col].fillna('').astype(str)
df[f'{col}_len'] = s.str.len()
df[f'{col}_digit_ratio'] = s.apply(lambda x: sum((c.isdigit() for c in x)) / max(len(x), 1))
return df
|