sony9316 commited on
Commit
6419184
Β·
verified Β·
1 Parent(s): 9f55fd3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -18
app.py CHANGED
@@ -185,7 +185,10 @@ def calculate_threshold_metrics(df, threshold_minutes, scope="all"):
185
  # Cancellation metrics - now much more accurate
186
  current_cancellations = int(df_with_prev["cancelled_due_to_previous_delay"].sum())
187
  cancellations_prevented = int(df_with_prev["cancellation_prevented"].sum())
188
- cancellation_rate = (current_cancellations / rentals_with_previous) * 100 if rentals_with_previous > 0 else 0
 
 
 
189
 
190
  return {
191
  "total_rentals": total_rentals,
@@ -317,22 +320,21 @@ if selected == "πŸ“Š Data Overview":
317
  col1, col2 = st.columns(2)
318
 
319
  with col1:
320
- # Delay status distribution
321
- df["delay_status"] = df["delay_at_checkout_in_minutes"].apply(
322
- lambda x: "Early Return" if pd.notnull(x) and x < 0 else
323
- "On Time" if pd.notnull(x) and x == 0 else
324
- "Late Return" if pd.notnull(x) and x > 0 else "Missing Data"
325
  )
326
 
327
- delay_counts = df["delay_status"].value_counts()
328
  fig_delay_status = px.pie(
329
  values=delay_counts.values,
330
  names=delay_counts.index,
331
- title="Return Status Distribution",
332
  color_discrete_sequence=px.colors.qualitative.Bold
333
  )
334
  fig_delay_status.update_layout(
335
- annotations=[dict(text="Missing Data = no checkout delay recorded",
336
  x=0.5, y=-0.1, xref="paper", yref="paper",
337
  showarrow=False, font=dict(size=10))]
338
  )
@@ -440,18 +442,24 @@ if selected == "πŸ“Š Data Overview":
440
  )
441
 
442
  delay_related_cancels = df_analysis["cancelled_due_to_previous_delay"].sum()
443
- total_cancels = (df_analysis["state"] == "canceled").sum()
 
444
 
445
  col2_1, col2_2 = st.columns(2)
446
  with col2_1:
447
- st.metric("Total Cancellations", f"{total_cancels:,}")
 
448
  with col2_2:
449
  st.metric("Due to Previous Delay", f"{delay_related_cancels:,}",
450
  help="Cancelled rentals where the previous rental on same car was late")
451
 
452
- if total_cancels > 0:
453
- delay_cancel_rate = (delay_related_cancels / total_cancels * 100)
454
- st.metric("% of Cancellations Due to Previous Delays", f"{delay_cancel_rate:.1f}%")
 
 
 
 
455
 
456
  # Problem cases analysis (including cancellations)
457
  st.markdown('<div class="section-header">🚨 Current Problem Cases Analysis</div>', unsafe_allow_html=True)
@@ -702,7 +710,7 @@ elif selected == "πŸ• Threshold Analysis":
702
  "Cancellations Prevented vs Threshold",
703
  "Efficiency (Solve Rate) vs Threshold",
704
  "Revenue Impact vs Threshold",
705
- "Cancellation Rate vs Threshold"
706
  )
707
  )
708
 
@@ -749,7 +757,7 @@ elif selected == "πŸ• Threshold Analysis":
749
  # Cancellation rate
750
  fig.add_trace(
751
  go.Scatter(x=sweep_df["threshold"], y=sweep_df["cancellation_rate"],
752
- mode="lines+markers", name="Cancellation Rate (%)",
753
  line=dict(color="#e67e22"), showlegend=False),
754
  row=2, col=3
755
  )
@@ -877,7 +885,7 @@ elif selected == "🎯 Scope Analysis":
877
  "Cancellations Prevented by Scope",
878
  "Efficiency by Scope",
879
  "Revenue Impact by Scope",
880
- "Cancellation Rate by Scope"
881
  )
882
  )
883
 
@@ -926,7 +934,7 @@ elif selected == "🎯 Scope Analysis":
926
  row=2, col=2
927
  )
928
 
929
- # Cancellation rate
930
  fig.add_trace(
931
  go.Scatter(x=scope_data["threshold"], y=scope_data["cancellation_rate"],
932
  mode="lines+markers", name=f"{scope_name}",
 
185
  # Cancellation metrics - now much more accurate
186
  current_cancellations = int(df_with_prev["cancelled_due_to_previous_delay"].sum())
187
  cancellations_prevented = int(df_with_prev["cancellation_prevented"].sum())
188
+
189
+ # Remaining cancellation rate after implementing threshold
190
+ remaining_cancellations = current_cancellations - cancellations_prevented
191
+ cancellation_rate = (remaining_cancellations / rentals_with_previous) * 100 if rentals_with_previous > 0 else 0
192
 
193
  return {
194
  "total_rentals": total_rentals,
 
320
  col1, col2 = st.columns(2)
321
 
322
  with col1:
323
+ # Delay status distribution (excluding missing data)
324
+ df_with_delay_data = df[df["delay_at_checkout_in_minutes"].notnull()].copy()
325
+ df_with_delay_data["delay_status"] = df_with_delay_data["delay_at_checkout_in_minutes"].apply(
326
+ lambda x: "Early Return" if x < 0 else "On Time" if x == 0 else "Late Return"
 
327
  )
328
 
329
+ delay_counts = df_with_delay_data["delay_status"].value_counts()
330
  fig_delay_status = px.pie(
331
  values=delay_counts.values,
332
  names=delay_counts.index,
333
+ title="Return Status Distribution (Data Available Only)",
334
  color_discrete_sequence=px.colors.qualitative.Bold
335
  )
336
  fig_delay_status.update_layout(
337
+ annotations=[dict(text=f"Based on {len(df_with_delay_data):,} rentals with delay data",
338
  x=0.5, y=-0.1, xref="paper", yref="paper",
339
  showarrow=False, font=dict(size=10))]
340
  )
 
442
  )
443
 
444
  delay_related_cancels = df_analysis["cancelled_due_to_previous_delay"].sum()
445
+ total_cancels_with_prev = (df_analysis["state"] == "canceled").sum()
446
+ total_cancels_all = (df["state"] == "canceled").sum()
447
 
448
  col2_1, col2_2 = st.columns(2)
449
  with col2_1:
450
+ st.metric("Total Cancellations (All)", f"{total_cancels_all:,}",
451
+ help="All cancelled rentals in the dataset")
452
  with col2_2:
453
  st.metric("Due to Previous Delay", f"{delay_related_cancels:,}",
454
  help="Cancelled rentals where the previous rental on same car was late")
455
 
456
+ if total_cancels_all > 0:
457
+ delay_cancel_rate = (delay_related_cancels / total_cancels_all * 100)
458
+ st.metric("% of All Cancellations Due to Previous Delays", f"{delay_cancel_rate:.1f}%")
459
+
460
+ # Additional context
461
+ st.info(f"Note: {total_cancels_with_prev:,} cancellations had previous rentals (analyzed for delay impact)")
462
+
463
 
464
  # Problem cases analysis (including cancellations)
465
  st.markdown('<div class="section-header">🚨 Current Problem Cases Analysis</div>', unsafe_allow_html=True)
 
710
  "Cancellations Prevented vs Threshold",
711
  "Efficiency (Solve Rate) vs Threshold",
712
  "Revenue Impact vs Threshold",
713
+ "Remaining Cancellation Rate vs Threshold"
714
  )
715
  )
716
 
 
757
  # Cancellation rate
758
  fig.add_trace(
759
  go.Scatter(x=sweep_df["threshold"], y=sweep_df["cancellation_rate"],
760
+ mode="lines+markers", name="Remaining Cancellation Rate (%)",
761
  line=dict(color="#e67e22"), showlegend=False),
762
  row=2, col=3
763
  )
 
885
  "Cancellations Prevented by Scope",
886
  "Efficiency by Scope",
887
  "Revenue Impact by Scope",
888
+ "Remaining Cancellation Rate by Scope"
889
  )
890
  )
891
 
 
934
  row=2, col=2
935
  )
936
 
937
+ # Remaining cancellation rate
938
  fig.add_trace(
939
  go.Scatter(x=scope_data["threshold"], y=scope_data["cancellation_rate"],
940
  mode="lines+markers", name=f"{scope_name}",