GenAICoder commited on
Commit
10d50f1
·
verified ·
1 Parent(s): e03bba4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -2
app.py CHANGED
@@ -430,8 +430,70 @@ def generate_portfolio_overview(as_of_month, segment):
430
  """
431
  df = _filter_master_by_month(as_of_month)
432
 
433
- # If segment filtering required in future, `segment` param can be used to filter further
 
 
 
 
 
 
434
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
435
  total_accounts = df["account_id"].nunique() if "account_id" in df.columns else 0
436
 
437
  open_accounts = (
@@ -470,7 +532,6 @@ def generate_portfolio_overview(as_of_month, segment):
470
  if "fico_score" in df.columns:
471
  avg_fico = round(df["fico_score"].dropna().mean(), 1)
472
  elif "fico_band" in df.columns:
473
- # attempt to map band midpoints like "600-650" -> 625
474
  def band_mid(b):
475
  try:
476
  parts = b.split("-")
 
430
  """
431
  df = _filter_master_by_month(as_of_month)
432
 
433
+ # If a segmentation column is provided, return per-segment breakdown
434
+ valid_segments = [
435
+ "fico_band",
436
+ "sourcing_channel",
437
+ "city_tier",
438
+ "occupation_type"
439
+ ]
440
 
441
+ if segment in valid_segments and segment in df.columns:
442
+ grp = segment
443
+
444
+ total_accounts = df.groupby(grp)["account_id"].nunique()
445
+
446
+ if "balance" in df.columns:
447
+ open_accounts = (
448
+ df.loc[df["balance"] > 0].groupby(grp)["account_id"].nunique()
449
+ )
450
+ total_balance = df.groupby(grp)["balance"].sum()
451
+ else:
452
+ open_accounts = pd.Series(0, index=total_accounts.index)
453
+ total_balance = pd.Series(0, index=total_accounts.index)
454
+
455
+ if "dpd" in df.columns:
456
+ bad_accounts = (
457
+ df.loc[df["dpd"].fillna(0) >= 30].groupby(grp)["account_id"].nunique()
458
+ )
459
+ bad_balance = (
460
+ df.assign(_bad_balance=df["balance"].where(df["dpd"].fillna(0) >= 30, 0))
461
+ .groupby(grp)["_bad_balance"].sum()
462
+ ) if "balance" in df.columns else pd.Series(0, index=total_accounts.index)
463
+ else:
464
+ bad_accounts = pd.Series(0, index=total_accounts.index)
465
+ bad_balance = pd.Series(0, index=total_accounts.index)
466
+
467
+ # NCL if present
468
+ ncl_cols = [c for c in df.columns if "ncl" in c.lower()]
469
+ if len(ncl_cols) > 0:
470
+ total_ncl = df.groupby(grp)[ncl_cols[0]].sum()
471
+ ncl_rate = (total_ncl / total_balance * 100).round(2).fillna(0)
472
+ else:
473
+ ncl_rate = (bad_balance / total_balance * 100).round(2).fillna(0)
474
+
475
+ # average fico per group if available
476
+ if "fico_score" in df.columns:
477
+ avg_fico = df.groupby(grp)["fico_score"].mean().round(1)
478
+ else:
479
+ avg_fico = pd.Series(float("nan"), index=total_accounts.index)
480
+
481
+ result = pd.DataFrame({
482
+ "Segment": total_accounts.index,
483
+ "Total_Accounts": total_accounts.values,
484
+ "Open_Accounts": open_accounts.reindex(total_accounts.index).fillna(0).astype(int).values,
485
+ "Bad_Accounts": bad_accounts.reindex(total_accounts.index).fillna(0).astype(int).values,
486
+ "Total_Balance": total_balance.reindex(total_accounts.index).fillna(0).values,
487
+ "NCL_Rate_pct": ncl_rate.reindex(total_accounts.index).fillna(0).values,
488
+ "Avg_FICO": avg_fico.reindex(total_accounts.index).fillna(float("nan")).values
489
+ })
490
+
491
+ # Sort by NCL rate descending
492
+ result = result.sort_values("NCL_Rate_pct", ascending=False).reset_index(drop=True)
493
+
494
+ return result
495
+
496
+ # Default: single-line overview
497
  total_accounts = df["account_id"].nunique() if "account_id" in df.columns else 0
498
 
499
  open_accounts = (
 
532
  if "fico_score" in df.columns:
533
  avg_fico = round(df["fico_score"].dropna().mean(), 1)
534
  elif "fico_band" in df.columns:
 
535
  def band_mid(b):
536
  try:
537
  parts = b.split("-")