SHELLAPANDIANGANHUNGING commited on
Commit
92acfae
·
verified ·
1 Parent(s): e45b23a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -43
app.py CHANGED
@@ -598,75 +598,70 @@ findings_by_location_month = df_local.groupby(['created_month', 'nama_lokasi_ful
598
  creators_by_location_month = df_local.groupby(['created_month', 'nama_lokasi_full'])['creator_nid'].nunique().reset_index(name='unique_creators')
599
  # Gabung
600
  merged_loc = findings_by_location_month.merge(creators_by_location_month, on=['created_month', 'nama_lokasi_full'], how='outer')
601
- # Isi NaN dengan 0 untuk kolom yang mungkin hilang dari merge
602
  merged_loc = merged_loc.fillna({'findings_count': 0, 'unique_creators': 0})
603
- # Filter untuk menghindari pembagian dengan nol
604
  merged_loc = merged_loc[merged_loc['unique_creators'] > 0]
605
- # Hitung rasio (ignore NaN)
606
  merged_loc['ratio'] = merged_loc['findings_count'] / merged_loc['unique_creators']
607
  merged_loc['ratio'] = merged_loc['ratio'].replace([np.inf, -np.inf], np.nan)
608
 
609
  # Rata-rata bulanan per lokasi
610
  avg_ratio_per_location = merged_loc.groupby('nama_lokasi_full')['ratio'].mean().reset_index(name='avg_monthly_ratio')
611
-
612
- # Filter hasil akhir untuk menghindari NaN
613
  avg_ratio_per_location = avg_ratio_per_location.dropna(subset=['avg_monthly_ratio'])
614
 
615
  if avg_ratio_per_location.empty:
616
  st.write("Data kosong.")
617
  else:
618
- # Treemap dengan gradasi warna merah kuning → hijau
619
  fig_treemap = px.treemap(
620
  avg_ratio_per_location,
621
- path=['nama_lokasi_full'], # Hierarki (single level)
622
- values='avg_monthly_ratio', # Ukuran area
623
- title='Avg Monthly Finding by Location',
624
  labels={
625
  'avg_monthly_ratio': 'Avg Monthly Finding/Person Ratio',
626
  'nama_lokasi_full': 'Location'
627
  },
628
- color='avg_monthly_ratio', # Warna berdasarkan nilai rasio
629
  color_continuous_scale=[
630
- [0.0, '#D32F2F'], # Merah (rendah)
631
- [0.5, '#FFB300'], # Kuning (sedang)
632
- [1.0, '#4CAF50'] # Hijau (tinggi)
633
- ]
 
634
  )
635
 
636
- st.plotly_chart(fig_treemap, use_container_width=True)
637
-
638
- # Format hover
639
  fig_treemap.update_traces(
640
  hovertemplate="<b>%{label}</b><br>Avg Ratio: %{value:.2f}<extra></extra>"
641
  )
642
- fig_treemap.update_layout(height=600)
643
- st.plotly_chart(fig_treemap, use_container_width=True)
 
 
 
644
 
645
- # AI Insight untuk Treemap Lokasi (Business-focused)
646
- if not avg_ratio_per_location.empty:
647
- # Temukan lokasi dengan rasio tertinggi dan terendah
648
- top_location = avg_ratio_per_location.loc[avg_ratio_per_location['avg_monthly_ratio'].idxmax()]
649
- low_location = avg_ratio_per_location.loc[avg_ratio_per_location['avg_monthly_ratio'].idxmin()]
650
-
651
- st.markdown("### Insight")
652
- insight_text = (
653
- # f"<div class='ai-insight'>"
654
- # f"The treemap visualizes the average finding-to-person ratio per location using a <strong>color gradient</strong>, indicating reporting activity levels. "
655
- # f"Locations with <span style='color:#4CAF50; font-weight:bold;'>green</span> color have a high ratio, indicating high reporting activity or exposure. "
656
- # f"Those with <span style='color:#FFB300; font-weight:bold;'>yellow</span> color have a medium ratio, indicating moderate reporting. "
657
- # f"Locations with <span style='color:#D32F2F; font-weight:bold;'>red</span> color have a low ratio, indicating lower activity levels or potentially under-reporting. "
658
- f"<strong>{top_location['nama_lokasi_full']}</strong> shows the highest activity level "
659
- f"(<strong>{top_location['avg_monthly_ratio']:.2f}</strong>). "
660
- f"<strong>{low_location['nama_lokasi_full']}</strong> is one of areas with the lowest activity level "
661
- f"(<strong>{low_location['avg_monthly_ratio']:.2f}</strong>). "
662
- f"Areas with high activity (green) warrant inspection into the underlying causes of frequent findings. "
663
- f"Areas with low activity (red) should be reviewed to ensure reporting completeness and identify any hidden risks."
664
- f"</div>"
665
- )
666
- st.markdown(insight_text, unsafe_allow_html=True)
667
- else:
668
- st.warning("No data available for location ratio calculation or all ratios are NaN.")
669
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
670
  # =================== OBJECTIVE 3 - Frequency & Response Time ===================
671
  st.markdown(
672
  """
 
598
  creators_by_location_month = df_local.groupby(['created_month', 'nama_lokasi_full'])['creator_nid'].nunique().reset_index(name='unique_creators')
599
  # Gabung
600
  merged_loc = findings_by_location_month.merge(creators_by_location_month, on=['created_month', 'nama_lokasi_full'], how='outer')
601
+ # Isi NaN dengan 0
602
  merged_loc = merged_loc.fillna({'findings_count': 0, 'unique_creators': 0})
603
+ # Hindari pembagian dengan nol
604
  merged_loc = merged_loc[merged_loc['unique_creators'] > 0]
605
+ # Hitung rasio
606
  merged_loc['ratio'] = merged_loc['findings_count'] / merged_loc['unique_creators']
607
  merged_loc['ratio'] = merged_loc['ratio'].replace([np.inf, -np.inf], np.nan)
608
 
609
  # Rata-rata bulanan per lokasi
610
  avg_ratio_per_location = merged_loc.groupby('nama_lokasi_full')['ratio'].mean().reset_index(name='avg_monthly_ratio')
 
 
611
  avg_ratio_per_location = avg_ratio_per_location.dropna(subset=['avg_monthly_ratio'])
612
 
613
  if avg_ratio_per_location.empty:
614
  st.write("Data kosong.")
615
  else:
616
+ # Treemap hanya dibuat & ditampilkan sekali
617
  fig_treemap = px.treemap(
618
  avg_ratio_per_location,
619
+ path=['nama_lokasi_full'],
620
+ values='avg_monthly_ratio',
621
+ title='Avg Monthly Finding/Person Ratio by Location',
622
  labels={
623
  'avg_monthly_ratio': 'Avg Monthly Finding/Person Ratio',
624
  'nama_lokasi_full': 'Location'
625
  },
626
+ color='avg_monthly_ratio',
627
  color_continuous_scale=[
628
+ [0.0, '#D32F2F'], # Red (low activity)
629
+ [0.5, '#FFB300'], # Amber/orange-yellow (medium)
630
+ [1.0, '#4CAF50'] # Green (high activity)
631
+ ],
632
+ hover_data={'avg_monthly_ratio': ':.2f'} # pastikan format hover sudah 2 desimal
633
  )
634
 
635
+ # Perbaiki tata letak & hover — lakukan *sebelum* menampilkan
 
 
636
  fig_treemap.update_traces(
637
  hovertemplate="<b>%{label}</b><br>Avg Ratio: %{value:.2f}<extra></extra>"
638
  )
639
+ fig_treemap.update_layout(
640
+ title=dict(text='Avg Monthly Finding/Person Ratio by Location', x=0.5, xanchor='center'),
641
+ height=600,
642
+ margin=dict(t=50, l=25, r=25, b=25)
643
+ )
644
 
645
+ # Tampilkan hanya sekali!
646
+ st.plotly_chart(fig_treemap, use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
647
 
648
+ # === AI Insight ===
649
+ top_location = avg_ratio_per_location.loc[avg_ratio_per_location['avg_monthly_ratio'].idxmax()]
650
+ low_location = avg_ratio_per_location.loc[avg_ratio_per_location['avg_monthly_ratio'].idxmin()]
651
+
652
+ st.markdown("### Insight")
653
+ insight_text = (
654
+ f"<div class='ai-insight'>"
655
+ f"<strong>{top_location['nama_lokasi_full']}</strong> shows the highest activity level "
656
+ f"(<strong>{top_location['avg_monthly_ratio']:.2f}</strong> findings per person/month). "
657
+ f"In contrast, <strong>{low_location['nama_lokasi_full']}</strong> has the lowest activity level "
658
+ f"(<strong>{low_location['avg_monthly_ratio']:.2f}</strong>).<br><br>"
659
+ f"🟢 <strong>High-ratio (green)</strong> locations indicate either high reporting diligence or high exposure to risks — both warrant deeper root-cause analysis.<br>"
660
+ f"🔴 <strong>Low-ratio (red)</strong> locations may reflect under-reporting, lack of engagement, or low hazard visibility — recommend follow-up audits to verify data completeness.<br>"
661
+ f"🟡 Medium-ratio (yellow) areas need monitoring to ensure trends do not deteriorate."
662
+ f"</div>"
663
+ )
664
+ st.markdown(insight_text, unsafe_allow_html=True)
665
  # =================== OBJECTIVE 3 - Frequency & Response Time ===================
666
  st.markdown(
667
  """