SHELLAPANDIANGANHUNGING commited on
Commit
dcac95d
·
verified ·
1 Parent(s): 460601e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -74
app.py CHANGED
@@ -1473,52 +1473,52 @@ def predict_locations(df):
1473
  df_res = pd.DataFrame(results)
1474
  return df_res.sort_values('Trend Slope', ascending=True) if not df_res.empty else df_res # most negative first
1475
 
1476
- # ——————— 2. Divisions ———————
1477
- def predict_divisions(df):
1478
- if 'nama' not in df.columns:
1479
- return pd.DataFrame()
1480
 
1481
- start_month = df['created_at'].min().to_period('M')
1482
- end_month = df['created_at'].max().to_period('M')
1483
- all_months = pd.period_range(start=start_month, end=end_month, freq='M')
1484
 
1485
- df_monthly = (
1486
- df.groupby(['nama', df['created_at'].dt.to_period('M')])
1487
- .size()
1488
- .unstack(fill_value=0)
1489
- .reindex(columns=all_months, fill_value=0)
1490
- .stack()
1491
- .reset_index(name='count')
1492
- )
1493
- df_monthly.columns = ['Division', 'Month', 'Count']
1494
 
1495
- results = []
1496
- for div, group in df_monthly.groupby('Division'):
1497
- ts = group.set_index('Month')['Count']
1498
- total = len(all_months)
1499
- active = (ts > 0).sum()
1500
- gaps = total - active
1501
- coverage = active / total if total > 0 else 0
1502
 
1503
- if gaps > 2:
1504
- status = "<span class='status-inactive'>Inactive</span>"
1505
- elif gaps == 0:
1506
- status = "<span class='status-active'>Active</span>"
1507
- else:
1508
- status = "<span class='status-neutral'>Neutral</span>"
1509
 
1510
- bar = ''.join(['●' if c > 0 else '○' for c in ts.values])
1511
- trend_line = f"<span class='spark' style='color:#003DA5;'>{bar}</span>"
1512
- results.append({
1513
- 'Division': div,
1514
- 'Active Months': int(active),
1515
- 'Total Months': int(total),
1516
- 'Coverage (%)': round(coverage * 100, 1),
1517
- 'Status': status,
1518
- 'Trend': trend_line
1519
- })
1520
- df_res = pd.DataFrame(results)
1521
- return df_res.sort_values('Coverage (%)', ascending=True) if not df_res.empty else df_res
1522
 
1523
  # ——————— 3. Issues: ONLY Coverage=100% & Trend Slope > 0 → Avg/Month ———————
1524
  def predict_issues(df):
@@ -1615,39 +1615,39 @@ if not df_loc.empty:
1615
  # )
1616
  st.markdown("</div>", unsafe_allow_html=True)
1617
 
1618
- # 🎯 PANEL 2: Divisions
1619
- st.markdown("<div class='predictive-panel'>", unsafe_allow_html=True)
1620
- st.markdown("<div class='predictive-header'>2. Which Areas Are Likely to Be Frequently or Rarely Inspected?</div>", unsafe_allow_html=True)
1621
- if not df_div.empty:
1622
- cols = ['Division', 'Active Months', 'Total Months', 'Coverage (%)', 'Status', 'Trend']
1623
-
1624
- # 🔵 Rename ONLY for display (Status → Forecast Inspection)
1625
- df_display = df_div[cols].rename(columns={
1626
- "Status": "Forecast Inspection"
1627
- })
1628
-
1629
- html = df_display.to_html(escape=False, index=False, table_id="tbl-divisions")
1630
- st.markdown(f"<div class='predictive-table-wrapper'>{html}</div>", unsafe_allow_html=True)
1631
-
1632
- # st.markdown(
1633
- # "<div class='predictive-note'>"
1634
- # "<strong>Forecast Inspection:</strong> "
1635
- # "<span class='status-active'>Active</span> (0 gaps), "
1636
- # "<span class='status-neutral'>Neutral</span> (1–2 gaps), "
1637
- # "<span class='status-inactive'>Inactive</span> (>2 gaps)."
1638
- # "</div>",
1639
- # unsafe_allow_html=True
1640
- # )
1641
- # else:
1642
- # st.markdown(
1643
- # "<div class='predictive-table-wrapper'>"
1644
- # "<p style='text-align:center; color:#666; padding:24px; font-style:italic;'>"
1645
- # "Insufficient division data (≥2 months required)."
1646
- # "</p></div>",
1647
- # unsafe_allow_html=True
1648
- # )
1649
-
1650
- st.markdown("</div>", unsafe_allow_html=True)
1651
 
1652
 
1653
  # 🎯 PANEL 3: Issues (FILTERED: Coverage=100% & Rising)
 
1473
  df_res = pd.DataFrame(results)
1474
  return df_res.sort_values('Trend Slope', ascending=True) if not df_res.empty else df_res # most negative first
1475
 
1476
+ # # ——————— 2. Divisions ———————
1477
+ # def predict_divisions(df):
1478
+ # if 'nama' not in df.columns:
1479
+ # return pd.DataFrame()
1480
 
1481
+ # start_month = df['created_at'].min().to_period('M')
1482
+ # end_month = df['created_at'].max().to_period('M')
1483
+ # all_months = pd.period_range(start=start_month, end=end_month, freq='M')
1484
 
1485
+ # df_monthly = (
1486
+ # df.groupby(['nama', df['created_at'].dt.to_period('M')])
1487
+ # .size()
1488
+ # .unstack(fill_value=0)
1489
+ # .reindex(columns=all_months, fill_value=0)
1490
+ # .stack()
1491
+ # .reset_index(name='count')
1492
+ # )
1493
+ # df_monthly.columns = ['Division', 'Month', 'Count']
1494
 
1495
+ # results = []
1496
+ # for div, group in df_monthly.groupby('Division'):
1497
+ # ts = group.set_index('Month')['Count']
1498
+ # total = len(all_months)
1499
+ # active = (ts > 0).sum()
1500
+ # gaps = total - active
1501
+ # coverage = active / total if total > 0 else 0
1502
 
1503
+ # if gaps > 2:
1504
+ # status = "<span class='status-inactive'>Inactive</span>"
1505
+ # elif gaps == 0:
1506
+ # status = "<span class='status-active'>Active</span>"
1507
+ # else:
1508
+ # status = "<span class='status-neutral'>Neutral</span>"
1509
 
1510
+ # bar = ''.join(['●' if c > 0 else '○' for c in ts.values])
1511
+ # trend_line = f"<span class='spark' style='color:#003DA5;'>{bar}</span>"
1512
+ # results.append({
1513
+ # 'Division': div,
1514
+ # 'Active Months': int(active),
1515
+ # 'Total Months': int(total),
1516
+ # 'Coverage (%)': round(coverage * 100, 1),
1517
+ # 'Status': status,
1518
+ # 'Trend': trend_line
1519
+ # })
1520
+ # df_res = pd.DataFrame(results)
1521
+ # return df_res.sort_values('Coverage (%)', ascending=True) if not df_res.empty else df_res
1522
 
1523
  # ——————— 3. Issues: ONLY Coverage=100% & Trend Slope > 0 → Avg/Month ———————
1524
  def predict_issues(df):
 
1615
  # )
1616
  st.markdown("</div>", unsafe_allow_html=True)
1617
 
1618
+ # # 🎯 PANEL 2: Divisions
1619
+ # st.markdown("<div class='predictive-panel'>", unsafe_allow_html=True)
1620
+ # st.markdown("<div class='predictive-header'>2. Which Areas Are Likely to Be Frequently or Rarely Inspected?</div>", unsafe_allow_html=True)
1621
+ # if not df_div.empty:
1622
+ # cols = ['Division', 'Active Months', 'Total Months', 'Coverage (%)', 'Status', 'Trend']
1623
+
1624
+ # # 🔵 Rename ONLY for display (Status → Forecast Inspection)
1625
+ # df_display = df_div[cols].rename(columns={
1626
+ # "Status": "Forecast Inspection"
1627
+ # })
1628
+
1629
+ # html = df_display.to_html(escape=False, index=False, table_id="tbl-divisions")
1630
+ # st.markdown(f"<div class='predictive-table-wrapper'>{html}</div>", unsafe_allow_html=True)
1631
+
1632
+ # # st.markdown(
1633
+ # # "<div class='predictive-note'>"
1634
+ # # "<strong>Forecast Inspection:</strong> "
1635
+ # # "<span class='status-active'>Active</span> (0 gaps), "
1636
+ # # "<span class='status-neutral'>Neutral</span> (1–2 gaps), "
1637
+ # # "<span class='status-inactive'>Inactive</span> (>2 gaps)."
1638
+ # # "</div>",
1639
+ # # unsafe_allow_html=True
1640
+ # # )
1641
+ # # else:
1642
+ # # st.markdown(
1643
+ # # "<div class='predictive-table-wrapper'>"
1644
+ # # "<p style='text-align:center; color:#666; padding:24px; font-style:italic;'>"
1645
+ # # "Insufficient division data (≥2 months required)."
1646
+ # # "</p></div>",
1647
+ # # unsafe_allow_html=True
1648
+ # # )
1649
+
1650
+ # st.markdown("</div>", unsafe_allow_html=True)
1651
 
1652
 
1653
  # 🎯 PANEL 3: Issues (FILTERED: Coverage=100% & Rising)