Spaces:
Sleeping
Sleeping
Update app.py
Browse files
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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("-")
|