Skip to content

Loan Terms & Cashflow EDA #2

Description

@RigelAlgebar

Issue 2 – Loan Terms & Cashflow EDA with OOP + Per-Column Functional Summary

Goal
Analyze how loan terms and cashflows behave and how they relate to loan_status.

You must use:

  • OOP: create a class that encapsulates loan-terms EDA.
  • Functional programming: build a per-column numeric summary using a dict comprehension or map.

Columns in scope

You are responsible for the following columns:

Loan structure & pricing

  • loan_amnt
  • funded_amnt
  • funded_amnt_inv
  • term
  • int_rate
  • installment
  • grade
  • sub_grade
  • initial_list_status

Cashflow / lifecycle

  • out_prncp
  • out_prncp_inv
  • total_pymnt
  • total_pymnt_inv
  • total_rec_prncp
  • total_rec_int
  • total_rec_late_fee
  • recoveries
  • collection_recovery_fee
  • last_pymnt_d
  • last_pymnt_amnt
  • next_pymnt_d

Shared target

  • loan_status (used for default-rate calculations)

Files to edit

  • src/eda_loan_terms.py
  • notebooks/eda_loan_terms_demo.ipynb

1. Implement the LoanTermsEDA class

In src/eda_loan_terms.py, create and implement:

"""
import pandas as pd
from typing import Dict, Any, List

NUMERIC_TERM_COLS = [
"loan_amnt", "funded_amnt", "funded_amnt_inv",
"int_rate", "installment",
"out_prncp", "out_prncp_inv",
"total_pymnt", "total_pymnt_inv",
"total_rec_prncp", "total_rec_int",
"total_rec_late_fee", "recoveries", "collection_recovery_fee",
"last_pymnt_amnt",
]

CATEGORICAL_TERM_COLS = [
"term", "grade", "sub_grade", "initial_list_status",
]

class LoanTermsEDA:
def init(self, df: pd.DataFrame, target_col: str = "loan_status"):
"""
Store the full DataFrame and the name of the target column.
"""
self.df = df
self.target_col = target_col

def numeric_terms_summary(self) -> pd.DataFrame:
    """
    Return df[NUMERIC_TERM_COLS].describe().T
    (one row per numeric term/cashflow column).
    """
    ...

def distribution_stats_for_column(self, col: str) -> Dict[str, float]:
    """
    For a given numeric column, return stats in a dict:
    - mean
    - std
    - min
    - max
    - q25 (25% quantile)
    - q50 (median)
    - q75 (75% quantile)
    """
    ...

def default_rate_by_term(self) -> pd.Series:
    """
    Default rate (mean of target) per 'term' category.
    """
    ...

def default_rate_by_grade(self) -> pd.Series:
    """
    Default rate per 'grade' (or per 'sub_grade', if you prefer).
    """
    ...

"""


2. Functional per-column numeric summary

Add a function that uses functional programming over numeric columns:

"""
def summarize_numeric_terms(eda: LoanTermsEDA) -> Dict[str, Dict[str, float]]:
"""
For each column in NUMERIC_TERM_COLS, call
eda.distribution_stats_for_column(col) and return a dict:
col_name -> stats_dict.

Implement this using a dict comprehension or map
to clearly show functional style.
"""
...

"""

Example idea:

"""
def summarize_numeric_terms(eda: LoanTermsEDA) -> Dict[str, Dict[str, float]]:
return {col: eda.distribution_stats_for_column(col) for col in NUMERIC_TERM_COLS}
"""


3. Create the demo notebook

In notebooks/eda_loan_terms_demo.ipynb:

  1. Load the dataset:

"""
import pandas as pd
from src.eda_loan_terms import LoanTermsEDA, summarize_numeric_terms

df = pd.read_csv("data/loan_sample.csv") # or the correct path
"""

  1. Instantiate the EDA class:

"""
eda = LoanTermsEDA(df, target_col="loan_status")
"""

  1. Run EDA:

"""
numeric_summary = eda.numeric_terms_summary()
per_column_stats = summarize_numeric_terms(eda)
default_by_term = eda.default_rate_by_term()
default_by_grade = eda.default_rate_by_grade()
"""

  1. Display at least:

"""
numeric_summary # describe() table of numeric loan terms
per_column_stats # dict of stats per numeric column
default_by_term # default rate by term (e.g., 36 vs 60 months)
default_by_grade # default rate by grade/sub_grade
"""

Optionally add a histogram of int_rate or loan_amnt and a short markdown comment.
(But no modeling, only EDA.)


Acceptance Criteria ✅

  • LoanTermsEDA:

    • Initializes correctly with a DataFrame.
    • numeric_terms_summary() returns a DataFrame with one row per numeric term column.
    • distribution_stats_for_column(col) returns a stats dict for that column.
    • default_rate_by_term() and default_rate_by_grade() return Series with default rates.
  • Functional part:

    • summarize_numeric_terms(eda) uses a functional style (e.g. dict comprehension or map) to iterate over NUMERIC_TERM_COLS and call a method for each.
  • Notebook:

    • Runs top-to-bottom with no errors.
    • Shows numeric summaries, per-column stats, and default-rate-by-category analyses.
    • Contains only EDA (no model training).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions