GenAICoder commited on
Commit
8582913
·
verified ·
1 Parent(s): 5b7f9f3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +167 -193
app.py CHANGED
@@ -3,6 +3,10 @@
3
  import pandas as pd
4
  import gradio as gr
5
 
 
 
 
 
6
  from helper.vintage_helpers import (
7
  create_booking_vintage
8
  )
@@ -11,11 +15,19 @@ from helper.data_merger import (
11
  merge_acq_perf
12
  )
13
 
 
 
 
 
14
  from metrics.mix_metrics import (
15
  calculate_vintage_mix,
16
  calculate_limit_mix
17
  )
18
 
 
 
 
 
19
  from analytics.performance_analysis import (
20
  generate_metric_view
21
  )
@@ -33,38 +45,41 @@ perf = pd.read_csv(
33
  )
34
 
35
  # ---------------------------------------------------
36
- # CREATE VINTAGE
37
  # ---------------------------------------------------
38
 
39
- acq = create_booking_vintage(acq)
 
 
 
40
 
41
  # ---------------------------------------------------
42
- # MERGE DATA
43
  # ---------------------------------------------------
44
 
45
  master_df = merge_acq_perf(
46
- acq,
47
- perf
48
  )
49
 
50
  # ---------------------------------------------------
51
- # ACQUISITION ANALYSIS ENGINE
52
  # ---------------------------------------------------
53
 
54
  def run_acquisition_analysis(
55
  analysis_type,
56
- dimension
57
  ):
58
 
59
- # ----------------------------------------
60
- # MIX ANALYSIS
61
- # ----------------------------------------
62
 
63
- if analysis_type == "Mix Analysis":
64
 
65
  result = (
66
  acq.groupby(
67
- ["booking_vintage", dimension]
68
  )
69
  .agg(
70
  count=("account_id", "nunique"),
@@ -82,34 +97,20 @@ def run_acquisition_analysis(
82
  result["count"] / vintage_total
83
  ) * 100
84
 
85
- result["rate"] = result["rate"].round(2)
86
-
87
- result = result.rename(
88
- columns={
89
- "booking_vintage": "vintage",
90
- dimension: "segment"
91
- }
92
  )
93
 
94
- return result[
95
- [
96
- "vintage",
97
- "segment",
98
- "count",
99
- "balance",
100
- "rate"
101
- ]
102
- ]
103
 
104
- # ----------------------------------------
105
- # LIMIT ANALYSIS
106
- # ----------------------------------------
107
-
108
- elif analysis_type == "Limit Analysis":
109
 
110
  result = (
111
  acq.groupby(
112
- ["booking_vintage", dimension]
113
  )
114
  .agg(
115
  count=("account_id", "nunique"),
@@ -127,40 +128,53 @@ def run_acquisition_analysis(
127
  result["balance"] / vintage_total
128
  ) * 100
129
 
130
- result["rate"] = result["rate"].round(2)
131
-
132
- result = result.rename(
133
- columns={
134
- "booking_vintage": "vintage",
135
- dimension: "segment"
136
- }
137
  )
138
 
139
- return result[
140
- [
141
- "vintage",
142
- "segment",
143
- "count",
144
- "balance",
145
- "rate"
146
- ]
147
- ]
148
-
149
  else:
150
 
151
  return pd.DataFrame()
152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
  # ---------------------------------------------------
155
- # PERFORMANCE ANALYSIS ENGINE
156
  # ---------------------------------------------------
157
 
158
  def run_performance_analysis(
159
  metric_name,
160
- portfolio_view
161
  ):
162
 
163
- group_mapping = {
 
 
 
 
164
 
165
  "Overall": None,
166
 
@@ -177,176 +191,138 @@ def run_performance_analysis(
177
  "occupation_type"
178
  }
179
 
180
- group_col = group_mapping[
181
- portfolio_view
182
  ]
183
 
 
 
 
 
184
  result = generate_metric_view(
185
  df=master_df,
186
  metric_name=metric_name,
187
  group_col=group_col
188
  )
189
 
190
- # ----------------------------------------
191
- # IDENTIFY METRIC COLUMN
192
- # ----------------------------------------
193
-
194
- metric_col = [
195
- col for col in result.columns
196
- if "rate" in col.lower()
197
- ][0]
198
-
199
- # ----------------------------------------
200
- # STANDARDIZED OUTPUT
201
- # ----------------------------------------
202
 
203
  if group_col is not None:
204
 
205
- final_result = result.rename(
206
  columns={
207
- group_col: "segment",
208
- metric_col: "rate"
209
  }
210
  )
211
 
212
  else:
213
 
214
- final_result = result.rename(
215
- columns={
216
- metric_col: "rate"
217
- }
218
- )
219
-
220
- final_result["segment"] = "Overall"
221
-
222
- # ----------------------------------------
223
- # BALANCE LOGIC
224
- # ----------------------------------------
225
-
226
- # Delinquency metrics
227
- if metric_name in [
228
- "30+@3",
229
- "30+@6",
230
- "60+@6"
231
- ]:
232
 
233
- if "bad_balance" in final_result.columns:
 
 
234
 
235
- final_result["balance"] = (
236
- final_result["bad_balance"]
237
- )
238
-
239
- else:
240
-
241
- final_result["balance"] = None
242
-
243
- # NCL metric
244
- elif metric_name == "Yr1 NCL":
245
-
246
- if "total_balance" in final_result.columns:
247
-
248
- final_result["balance"] = (
249
- final_result["total_balance"]
250
- )
251
-
252
- else:
253
 
254
- final_result["balance"] = None
 
 
255
 
256
- # ----------------------------------------
257
- # FINAL OUTPUT FORMAT
258
- # ----------------------------------------
259
 
260
- final_result = final_result.rename(
261
- columns={
262
- "booking_vintage": "vintage",
263
- "total_accounts": "count"
264
- }
265
  )
266
 
267
- required_cols = [
268
- "vintage",
269
- "segment",
270
- "count",
271
- "balance",
272
- "rate"
273
- ]
274
-
275
- for col in required_cols:
276
 
277
- if col not in final_result.columns:
 
 
278
 
279
- final_result[col] = None
 
 
280
 
281
- return final_result[
282
- required_cols
283
- ]
 
284
 
 
285
 
286
  # ---------------------------------------------------
287
- # DYNAMIC DROPDOWN LOGIC
288
  # ---------------------------------------------------
289
 
290
  def update_analysis_dropdown(
291
- dataset_type
292
  ):
293
 
294
- # ----------------------------------------
295
  # ACQUISITION
296
- # ----------------------------------------
297
 
298
- if dataset_type == "Acquisition":
299
 
300
  return gr.update(
301
  choices=[
302
- "Mix Analysis",
303
- "Limit Analysis"
304
  ],
305
- value="Mix Analysis"
306
  )
307
 
308
- # ----------------------------------------
309
  # PERFORMANCE
310
- # ----------------------------------------
311
 
312
- elif dataset_type == "Performance":
313
 
314
  return gr.update(
315
  choices=[
316
  "30+@3",
317
  "30+@6",
318
- "60+@6",
319
  "Yr1 NCL"
320
  ],
321
  value="30+@6"
322
  )
323
 
324
 
325
- def update_dimension_dropdown(
326
- dataset_type
327
  ):
328
 
329
- # ----------------------------------------
330
  # ACQUISITION
331
- # ----------------------------------------
332
 
333
- if dataset_type == "Acquisition":
334
 
335
  return gr.update(
336
  choices=[
337
- "sourcing_channel",
338
  "fico_band",
 
339
  "city_tier",
340
  "occupation_type"
341
  ],
342
- value="sourcing_channel"
343
  )
344
 
345
- # ----------------------------------------
346
  # PERFORMANCE
347
- # ----------------------------------------
348
 
349
- elif dataset_type == "Performance":
350
 
351
  return gr.update(
352
  choices=[
@@ -359,44 +335,42 @@ def update_dimension_dropdown(
359
  value="Overall"
360
  )
361
 
362
-
363
  # ---------------------------------------------------
364
  # MASTER ROUTER
365
  # ---------------------------------------------------
366
 
367
  def run_analysis(
368
- dataset_type,
369
- analysis_selection,
370
- dimension_selection
371
  ):
372
 
373
- # ----------------------------------------
374
- # ACQUISITION ANALYSIS
375
- # ----------------------------------------
376
 
377
- if dataset_type == "Acquisition":
378
 
379
  return run_acquisition_analysis(
380
- analysis_type=analysis_selection,
381
- dimension=dimension_selection
382
  )
383
 
384
- # ----------------------------------------
385
- # PERFORMANCE ANALYSIS
386
- # ----------------------------------------
387
 
388
- elif dataset_type == "Performance":
389
 
390
  return run_performance_analysis(
391
- metric_name=analysis_selection,
392
- portfolio_view=dimension_selection
393
  )
394
 
395
  else:
396
 
397
  return pd.DataFrame()
398
 
399
-
400
  # ---------------------------------------------------
401
  # GRADIO UI
402
  # ---------------------------------------------------
@@ -409,7 +383,7 @@ with gr.Blocks() as app:
409
 
410
  with gr.Row():
411
 
412
- dataset_type = gr.Dropdown(
413
  choices=[
414
  "Acquisition",
415
  "Performance"
@@ -418,45 +392,45 @@ with gr.Blocks() as app:
418
  label="Dataset"
419
  )
420
 
421
- analysis_selection = gr.Dropdown(
422
  choices=[
423
- "Mix Analysis",
424
- "Limit Analysis"
425
  ],
426
- value="Mix Analysis",
427
  label="Analysis"
428
  )
429
 
430
- dimension_selection = gr.Dropdown(
431
  choices=[
432
- "sourcing_channel",
433
  "fico_band",
 
434
  "city_tier",
435
  "occupation_type"
436
  ],
437
- value="sourcing_channel",
438
- label="Dimension"
439
  )
440
 
441
- # ----------------------------------------
442
  # DYNAMIC DROPDOWNS
443
- # ----------------------------------------
444
 
445
- dataset_type.change(
446
  fn=update_analysis_dropdown,
447
- inputs=dataset_type,
448
- outputs=analysis_selection
449
  )
450
 
451
- dataset_type.change(
452
- fn=update_dimension_dropdown,
453
- inputs=dataset_type,
454
- outputs=dimension_selection
455
  )
456
 
457
- # ----------------------------------------
458
  # RUN BUTTON
459
- # ----------------------------------------
460
 
461
  run_button = gr.Button(
462
  "Run Analysis"
@@ -467,9 +441,9 @@ with gr.Blocks() as app:
467
  run_button.click(
468
  fn=run_analysis,
469
  inputs=[
470
- dataset_type,
471
- analysis_selection,
472
- dimension_selection
473
  ],
474
  outputs=output_table
475
  )
 
3
  import pandas as pd
4
  import gradio as gr
5
 
6
+ # ---------------------------------------------------
7
+ # HELPERS
8
+ # ---------------------------------------------------
9
+
10
  from helper.vintage_helpers import (
11
  create_booking_vintage
12
  )
 
15
  merge_acq_perf
16
  )
17
 
18
+ # ---------------------------------------------------
19
+ # METRICS
20
+ # ---------------------------------------------------
21
+
22
  from metrics.mix_metrics import (
23
  calculate_vintage_mix,
24
  calculate_limit_mix
25
  )
26
 
27
+ # ---------------------------------------------------
28
+ # ANALYTICS
29
+ # ---------------------------------------------------
30
+
31
  from analytics.performance_analysis import (
32
  generate_metric_view
33
  )
 
45
  )
46
 
47
  # ---------------------------------------------------
48
+ # CREATE BOOKING VINTAGE
49
  # ---------------------------------------------------
50
 
51
+ acq = create_booking_vintage(
52
+ acq,
53
+ booking_date_col="booking_date"
54
+ )
55
 
56
  # ---------------------------------------------------
57
+ # CREATE MASTER PERFORMANCE DATASET
58
  # ---------------------------------------------------
59
 
60
  master_df = merge_acq_perf(
61
+ acq_df=acq,
62
+ perf_df=perf
63
  )
64
 
65
  # ---------------------------------------------------
66
+ # ACQUISITION ANALYSIS
67
  # ---------------------------------------------------
68
 
69
  def run_acquisition_analysis(
70
  analysis_type,
71
+ category
72
  ):
73
 
74
+ # -----------------------------------------
75
+ # PORTFOLIO MIX
76
+ # -----------------------------------------
77
 
78
+ if analysis_type == "Portfolio Mix":
79
 
80
  result = (
81
  acq.groupby(
82
+ ["booking_vintage", category]
83
  )
84
  .agg(
85
  count=("account_id", "nunique"),
 
97
  result["count"] / vintage_total
98
  ) * 100
99
 
100
+ result["rate"] = (
101
+ result["rate"]
102
+ .round(2)
 
 
 
 
103
  )
104
 
105
+ # -----------------------------------------
106
+ # CREDIT LINE CONCENTRATION
107
+ # -----------------------------------------
 
 
 
 
 
 
108
 
109
+ elif analysis_type == "Credit Line Concentration":
 
 
 
 
110
 
111
  result = (
112
  acq.groupby(
113
+ ["booking_vintage", category]
114
  )
115
  .agg(
116
  count=("account_id", "nunique"),
 
128
  result["balance"] / vintage_total
129
  ) * 100
130
 
131
+ result["rate"] = (
132
+ result["rate"]
133
+ .round(2)
 
 
 
 
134
  )
135
 
 
 
 
 
 
 
 
 
 
 
136
  else:
137
 
138
  return pd.DataFrame()
139
 
140
+ # -----------------------------------------
141
+ # STANDARDIZED OUTPUT
142
+ # -----------------------------------------
143
+
144
+ result = result.rename(
145
+ columns={
146
+ "booking_vintage": "Vintage",
147
+ category: "Category",
148
+ "count": "Count",
149
+ "balance": "Balance",
150
+ "rate": "Rate"
151
+ }
152
+ )
153
+
154
+ return result[
155
+ [
156
+ "Vintage",
157
+ "Category",
158
+ "Count",
159
+ "Balance",
160
+ "Rate"
161
+ ]
162
+ ]
163
 
164
  # ---------------------------------------------------
165
+ # PERFORMANCE ANALYSIS
166
  # ---------------------------------------------------
167
 
168
  def run_performance_analysis(
169
  metric_name,
170
+ view_level
171
  ):
172
 
173
+ # -----------------------------------------
174
+ # VIEW MAPPING
175
+ # -----------------------------------------
176
+
177
+ view_mapping = {
178
 
179
  "Overall": None,
180
 
 
191
  "occupation_type"
192
  }
193
 
194
+ group_col = view_mapping[
195
+ view_level
196
  ]
197
 
198
+ # -----------------------------------------
199
+ # CALL ANALYTICS ENGINE
200
+ # -----------------------------------------
201
+
202
  result = generate_metric_view(
203
  df=master_df,
204
  metric_name=metric_name,
205
  group_col=group_col
206
  )
207
 
208
+ # -----------------------------------------
209
+ # STANDARDIZE OUTPUT
210
+ # -----------------------------------------
 
 
 
 
 
 
 
 
 
211
 
212
  if group_col is not None:
213
 
214
+ result = result.rename(
215
  columns={
216
+ group_col: "Category"
 
217
  }
218
  )
219
 
220
  else:
221
 
222
+ result["Category"] = "Overall"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
+ # -----------------------------------------
225
+ # IDENTIFY RATE COLUMN
226
+ # -----------------------------------------
227
 
228
+ rate_col = [
229
+ col for col in result.columns
230
+ if "rate" in col.lower()
231
+ ][0]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
 
233
+ # -----------------------------------------
234
+ # OUTPUT FORMAT
235
+ # -----------------------------------------
236
 
237
+ final_result = pd.DataFrame()
 
 
238
 
239
+ final_result["Vintage"] = (
240
+ result["booking_vintage"]
 
 
 
241
  )
242
 
243
+ final_result["Category"] = (
244
+ result["Category"]
245
+ )
 
 
 
 
 
 
246
 
247
+ final_result["Count"] = (
248
+ result["total_accounts"]
249
+ )
250
 
251
+ final_result["Balance"] = (
252
+ result["total_balance"]
253
+ )
254
 
255
+ final_result["Rate"] = (
256
+ result[rate_col]
257
+ .round(2)
258
+ )
259
 
260
+ return final_result
261
 
262
  # ---------------------------------------------------
263
+ # DYNAMIC DROPDOWNS
264
  # ---------------------------------------------------
265
 
266
  def update_analysis_dropdown(
267
+ dataset
268
  ):
269
 
270
+ # -----------------------------------------
271
  # ACQUISITION
272
+ # -----------------------------------------
273
 
274
+ if dataset == "Acquisition":
275
 
276
  return gr.update(
277
  choices=[
278
+ "Portfolio Mix",
279
+ "Credit Line Concentration"
280
  ],
281
+ value="Portfolio Mix"
282
  )
283
 
284
+ # -----------------------------------------
285
  # PERFORMANCE
286
+ # -----------------------------------------
287
 
288
+ elif dataset == "Performance":
289
 
290
  return gr.update(
291
  choices=[
292
  "30+@3",
293
  "30+@6",
294
+ "30+@9",
295
  "Yr1 NCL"
296
  ],
297
  value="30+@6"
298
  )
299
 
300
 
301
+ def update_category_dropdown(
302
+ dataset
303
  ):
304
 
305
+ # -----------------------------------------
306
  # ACQUISITION
307
+ # -----------------------------------------
308
 
309
+ if dataset == "Acquisition":
310
 
311
  return gr.update(
312
  choices=[
 
313
  "fico_band",
314
+ "sourcing_channel",
315
  "city_tier",
316
  "occupation_type"
317
  ],
318
+ value="fico_band"
319
  )
320
 
321
+ # -----------------------------------------
322
  # PERFORMANCE
323
+ # -----------------------------------------
324
 
325
+ elif dataset == "Performance":
326
 
327
  return gr.update(
328
  choices=[
 
335
  value="Overall"
336
  )
337
 
 
338
  # ---------------------------------------------------
339
  # MASTER ROUTER
340
  # ---------------------------------------------------
341
 
342
  def run_analysis(
343
+ dataset,
344
+ analysis,
345
+ category
346
  ):
347
 
348
+ # -----------------------------------------
349
+ # ACQUISITION
350
+ # -----------------------------------------
351
 
352
+ if dataset == "Acquisition":
353
 
354
  return run_acquisition_analysis(
355
+ analysis_type=analysis,
356
+ category=category
357
  )
358
 
359
+ # -----------------------------------------
360
+ # PERFORMANCE
361
+ # -----------------------------------------
362
 
363
+ elif dataset == "Performance":
364
 
365
  return run_performance_analysis(
366
+ metric_name=analysis,
367
+ view_level=category
368
  )
369
 
370
  else:
371
 
372
  return pd.DataFrame()
373
 
 
374
  # ---------------------------------------------------
375
  # GRADIO UI
376
  # ---------------------------------------------------
 
383
 
384
  with gr.Row():
385
 
386
+ dataset_dropdown = gr.Dropdown(
387
  choices=[
388
  "Acquisition",
389
  "Performance"
 
392
  label="Dataset"
393
  )
394
 
395
+ analysis_dropdown = gr.Dropdown(
396
  choices=[
397
+ "Portfolio Mix",
398
+ "Credit Line Concentration"
399
  ],
400
+ value="Portfolio Mix",
401
  label="Analysis"
402
  )
403
 
404
+ category_dropdown = gr.Dropdown(
405
  choices=[
 
406
  "fico_band",
407
+ "sourcing_channel",
408
  "city_tier",
409
  "occupation_type"
410
  ],
411
+ value="fico_band",
412
+ label="Category / View"
413
  )
414
 
415
+ # -----------------------------------------
416
  # DYNAMIC DROPDOWNS
417
+ # -----------------------------------------
418
 
419
+ dataset_dropdown.change(
420
  fn=update_analysis_dropdown,
421
+ inputs=dataset_dropdown,
422
+ outputs=analysis_dropdown
423
  )
424
 
425
+ dataset_dropdown.change(
426
+ fn=update_category_dropdown,
427
+ inputs=dataset_dropdown,
428
+ outputs=category_dropdown
429
  )
430
 
431
+ # -----------------------------------------
432
  # RUN BUTTON
433
+ # -----------------------------------------
434
 
435
  run_button = gr.Button(
436
  "Run Analysis"
 
441
  run_button.click(
442
  fn=run_analysis,
443
  inputs=[
444
+ dataset_dropdown,
445
+ analysis_dropdown,
446
+ category_dropdown
447
  ],
448
  outputs=output_table
449
  )