irhamni commited on
Commit
2605500
·
verified ·
1 Parent(s): 2df7b5a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -43
app.py CHANGED
@@ -639,52 +639,67 @@ def load_default_files(force=False):
639
 
640
  # ============================================================
641
  # 6) FAKTOR WILAYAH — PER JENIS (PATCH UTAMA)
642
- # faktor_jenis = min(n_jenis / target68_jenis, 1.0)
643
- # target/pop sekolah & umum diambil dari POP_KAB/POP_PROV jika tersedia
644
- # target/pop khusus diambil dari POP_KHUSUS (gabungan)
645
  # ============================================================
646
 
647
  def _read_target_pop_per_jenis_from_pop(pop_df: pd.DataFrame, mode: str):
648
  """
649
  Mengambil mapping target/pop PER JENIS untuk sekolah & umum dari POP_KAB/POP_PROV
650
- jika file populasi kamu memang punya kolom per jenis.
651
 
652
  Return:
653
- dict: {
654
- "sekolah": (target_col, pop_col),
655
- "umum": (target_col, pop_col),
656
- }
657
- Kalau tidak ketemu, return None untuk kolom tersebut -> nanti dianggap 0.
658
  """
659
  if pop_df is None or pop_df.empty:
660
  return {"sekolah": (None, None), "umum": (None, None)}
661
 
662
- # Kandidat kolom target/pop per jenis (buat fleksibel)
663
- # Silakan tambahkan alias kolom kamu di sini bila beda penamaan
 
 
 
664
  sekolah_target = pick_col(pop_df, [
 
665
  "TARGET_SEKOLAH_68", "Target_Sekolah_68", "target_sekolah_68",
666
- "SAMPEL_SEKOLAH_68", "Sampel_Sekolah_68", "sampel_sekolah_68",
667
- "target68_sekolah", "Target68_Sekolah"
668
  ])
669
  sekolah_pop = pick_col(pop_df, [
 
670
  "POP_SEKOLAH", "Pop_Sekolah", "pop_sekolah",
671
  "POPULASI_SEKOLAH", "Populasi_Sekolah"
672
  ])
673
 
674
  umum_target = pick_col(pop_df, [
 
675
  "TARGET_UMUM_68", "Target_Umum_68", "target_umum_68",
676
- "SAMPEL_UMUM_68", "Sampel_Umum_68", "sampel_umum_68",
677
- "target68_umum", "Target68_Umum"
678
  ])
679
  umum_pop = pick_col(pop_df, [
 
680
  "POP_UMUM", "Pop_Umum", "pop_umum",
681
- "POPULASI_UMUM", "Populasi_Umum"
 
 
682
  ])
683
 
684
- return {
685
- "sekolah": (sekolah_target, sekolah_pop),
686
- "umum": (umum_target, umum_pop),
687
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
688
 
689
 
690
  def build_faktor_wilayah_jenis(
@@ -696,7 +711,7 @@ def build_faktor_wilayah_jenis(
696
  ):
697
  """
698
  Output: faktor per (wilayah x jenis)
699
- Kolom minimal:
700
  group_key, [Kab/Kota|Provinsi], Jenis,
701
  n_jenis, target_total_68_jenis, pop_total_jenis,
702
  coverage_jenis_%, faktor_penyesuaian_jenis, gap_target68_jenis
@@ -727,38 +742,41 @@ def build_faktor_wilayah_jenis(
727
  )
728
  base_n["Jenis"] = base_n["Jenis"].astype(str).str.lower().str.strip()
729
 
730
- # mapping target/pop sekolah & umum dari POP_KAB/POP_PROV (jika ada)
731
  tp_map = _read_target_pop_per_jenis_from_pop(pop_base.reset_index(), mode=mode)
732
 
733
- # siapkan kolom target/pop default
734
  base_n["target_total_68_jenis"] = 0.0
735
  base_n["pop_total_jenis"] = 0.0
736
 
737
- # isi sekolah & umum dari POP_KAB/POP_PROV bila kolomnya tersedia
 
 
738
  for j in ["sekolah", "umum"]:
739
  tcol, pcol = tp_map.get(j, (None, None))
740
- if tcol is None and pcol is None:
741
  continue
742
 
743
- # ambil series target/pop per wilayah
744
- # (pop_base masih set_index group_key)
745
- if not pop_base.empty:
746
- if tcol is not None and tcol in pop_base.columns:
747
- tser = pd.to_numeric(pop_base[tcol], errors="coerce").fillna(0.0)
748
- else:
749
- tser = pd.Series(0.0, index=pop_base.index)
750
 
751
- if pcol is not None and pcol in pop_base.columns:
752
- pser = pd.to_numeric(pop_base[pcol], errors="coerce").fillna(0.0)
753
- else:
754
- pser = pd.Series(0.0, index=pop_base.index)
 
 
755
 
756
- mask = base_n["Jenis"].eq(j)
757
- # map by index
758
- base_n.loc[mask, "target_total_68_jenis"] = base_n.loc[mask, "group_key"].map(tser).fillna(0.0).values
759
- base_n.loc[mask, "pop_total_jenis"] = base_n.loc[mask, "group_key"].map(pser).fillna(0.0).values
760
 
761
- # isi KHUSUS dari POP_KHUSUS (sum per wilayah)
 
 
762
  if pop_khusus is not None and not pop_khusus.empty:
763
  pk = pop_khusus.copy()
764
  pk["Target68_Total_Jenis"] = pd.to_numeric(pk.get("Target68_Total_Jenis", np.nan), errors="coerce").fillna(0.0)
@@ -783,14 +801,16 @@ def build_faktor_wilayah_jenis(
783
  base_n.loc[mask_khusus, "target_total_68_jenis"] = pd.to_numeric(tmp["target_total_68_jenis"], errors="coerce").fillna(0.0).values
784
  base_n.loc[mask_khusus, "pop_total_jenis"] = pd.to_numeric(tmp["pop_total_jenis"], errors="coerce").fillna(0.0).values
785
 
786
- # fallback pop dari target
 
 
787
  base_n["target_total_68_jenis"] = pd.to_numeric(base_n["target_total_68_jenis"], errors="coerce").fillna(0.0)
788
  base_n["pop_total_jenis"] = pd.to_numeric(base_n["pop_total_jenis"], errors="coerce").fillna(0.0)
789
 
790
  m_need_pop = (base_n["pop_total_jenis"] <= 0) & (base_n["target_total_68_jenis"] > 0)
791
  base_n.loc[m_need_pop, "pop_total_jenis"] = base_n.loc[m_need_pop, "target_total_68_jenis"] / float(FALLBACK_TARGET_RATIO)
792
 
793
- # faktor per jenis
794
  base_n["faktor_penyesuaian_jenis"] = [
795
  faktor_penyesuaian_total(n, t)
796
  for n, t in zip(
 
639
 
640
  # ============================================================
641
  # 6) FAKTOR WILAYAH — PER JENIS (PATCH UTAMA)
 
 
 
642
  # ============================================================
643
 
644
  def _read_target_pop_per_jenis_from_pop(pop_df: pd.DataFrame, mode: str):
645
  """
646
  Mengambil mapping target/pop PER JENIS untuk sekolah & umum dari POP_KAB/POP_PROV
647
+ sesuai nama kolom REAL di file Excel user.
648
 
649
  Return:
650
+ dict: {"sekolah": (target_col, pop_col), "umum": (target_col, pop_col)}
 
 
 
 
651
  """
652
  if pop_df is None or pop_df.empty:
653
  return {"sekolah": (None, None), "umum": (None, None)}
654
 
655
+ # =========================
656
+ # POP KAB (Data_populasi_Kab_kota_fixed.xlsx)
657
+ # - umum: jumlah_populasi_umum, Sampel_umum_68%
658
+ # - sekolah: jumlah_populasi_sekolah, Sampel_sekolah_68%
659
+ # =========================
660
  sekolah_target = pick_col(pop_df, [
661
+ "Sampel_sekolah_68%", "Sampel_sekolah_68", "SAMPEL_SEKOLAH_68%", "SAMPEL_SEKOLAH_68",
662
  "TARGET_SEKOLAH_68", "Target_Sekolah_68", "target_sekolah_68",
663
+ "SAMPEL_SEKOLAH_68", "Sampel_Sekolah_68"
 
664
  ])
665
  sekolah_pop = pick_col(pop_df, [
666
+ "jumlah_populasi_sekolah", "Jumlah_populasi_sekolah", "JUMLAH_POPULASI_SEKOLAH",
667
  "POP_SEKOLAH", "Pop_Sekolah", "pop_sekolah",
668
  "POPULASI_SEKOLAH", "Populasi_Sekolah"
669
  ])
670
 
671
  umum_target = pick_col(pop_df, [
672
+ "Sampel_umum_68%", "Sampel_umum_68", "SAMPEL_UMUM_68%", "SAMPEL_UMUM_68",
673
  "TARGET_UMUM_68", "Target_Umum_68", "target_umum_68",
674
+ "SAMPEL_UMUM_68", "Sampel_Umum_68"
 
675
  ])
676
  umum_pop = pick_col(pop_df, [
677
+ "jumlah_populasi_umum", "Jumlah_populasi_umum", "JUMLAH_POPULASI_UMUM",
678
  "POP_UMUM", "Pop_Umum", "pop_umum",
679
+ "POPULASI_UMUM", "Populasi_Umum",
680
+ # POP PROV umum:
681
+ "perpus_umum_prop", "Perpus_umum_prop", "PERPUS_UMUM_PROP"
682
  ])
683
 
684
+ # =========================
685
+ # POP PROV (Data_populasi_propinsi.xlsx)
686
+ # - sekolah: total_pend, total _sampel
687
+ # - umum: perpus_umum_prop, target dihitung jika tidak ada
688
+ # =========================
689
+ if str(mode).upper() == "PROV":
690
+ # override sekolah kalau ada kolom prov yang lebih spesifik
691
+ sekolah_pop2 = pick_col(pop_df, ["total_pend", "TOTAL_PEND", "total_penduduk", "Total Pend"])
692
+ sekolah_target2 = pick_col(pop_df, ["total _sampel", "total_sampel", "TOTAL_SAMPEL", "Total Sampel"])
693
+
694
+ if sekolah_pop2 is not None:
695
+ sekolah_pop = sekolah_pop2
696
+ if sekolah_target2 is not None:
697
+ sekolah_target = sekolah_target2
698
+
699
+ # umum target prov kadang tidak ada -> akan dihitung dari pop (0.68 * pop) di bawah
700
+ # (jadi umum_target boleh None)
701
+
702
+ return {"sekolah": (sekolah_target, sekolah_pop), "umum": (umum_target, umum_pop)}
703
 
704
 
705
  def build_faktor_wilayah_jenis(
 
711
  ):
712
  """
713
  Output: faktor per (wilayah x jenis)
714
+ Kolom:
715
  group_key, [Kab/Kota|Provinsi], Jenis,
716
  n_jenis, target_total_68_jenis, pop_total_jenis,
717
  coverage_jenis_%, faktor_penyesuaian_jenis, gap_target68_jenis
 
742
  )
743
  base_n["Jenis"] = base_n["Jenis"].astype(str).str.lower().str.strip()
744
 
745
+ # mapping kolom target/pop sesuai Excel user
746
  tp_map = _read_target_pop_per_jenis_from_pop(pop_base.reset_index(), mode=mode)
747
 
748
+ # default 0 (biar tidak NaN)
749
  base_n["target_total_68_jenis"] = 0.0
750
  base_n["pop_total_jenis"] = 0.0
751
 
752
+ # =========================
753
+ # sekolah & umum dari POP_KAB / POP_PROV
754
+ # =========================
755
  for j in ["sekolah", "umum"]:
756
  tcol, pcol = tp_map.get(j, (None, None))
757
+ if pop_base.empty:
758
  continue
759
 
760
+ # pop
761
+ if pcol is not None and pcol in pop_base.columns:
762
+ pser = pd.to_numeric(pop_base[pcol], errors="coerce").fillna(0.0)
763
+ else:
764
+ pser = pd.Series(0.0, index=pop_base.index)
 
 
765
 
766
+ # target (kalau tidak ada kolom target khusus—khususnya PROV untuk umum—hitung dari pop)
767
+ if tcol is not None and tcol in pop_base.columns:
768
+ tser = pd.to_numeric(pop_base[tcol], errors="coerce").fillna(0.0)
769
+ else:
770
+ # fallback: target = 0.68 * pop (khusus PROV untuk umum biasanya)
771
+ tser = (pser.astype(float) * float(FALLBACK_TARGET_RATIO)).fillna(0.0)
772
 
773
+ mask = base_n["Jenis"].eq(j)
774
+ base_n.loc[mask, "pop_total_jenis"] = base_n.loc[mask, "group_key"].map(pser).fillna(0.0).values
775
+ base_n.loc[mask, "target_total_68_jenis"] = base_n.loc[mask, "group_key"].map(tser).fillna(0.0).values
 
776
 
777
+ # =========================
778
+ # KHUSUS dari POP_KHUSUS (sum per wilayah)
779
+ # =========================
780
  if pop_khusus is not None and not pop_khusus.empty:
781
  pk = pop_khusus.copy()
782
  pk["Target68_Total_Jenis"] = pd.to_numeric(pk.get("Target68_Total_Jenis", np.nan), errors="coerce").fillna(0.0)
 
801
  base_n.loc[mask_khusus, "target_total_68_jenis"] = pd.to_numeric(tmp["target_total_68_jenis"], errors="coerce").fillna(0.0).values
802
  base_n.loc[mask_khusus, "pop_total_jenis"] = pd.to_numeric(tmp["pop_total_jenis"], errors="coerce").fillna(0.0).values
803
 
804
+ # =========================
805
+ # fallback pop dari target (kalau pop masih 0 tapi target ada)
806
+ # =========================
807
  base_n["target_total_68_jenis"] = pd.to_numeric(base_n["target_total_68_jenis"], errors="coerce").fillna(0.0)
808
  base_n["pop_total_jenis"] = pd.to_numeric(base_n["pop_total_jenis"], errors="coerce").fillna(0.0)
809
 
810
  m_need_pop = (base_n["pop_total_jenis"] <= 0) & (base_n["target_total_68_jenis"] > 0)
811
  base_n.loc[m_need_pop, "pop_total_jenis"] = base_n.loc[m_need_pop, "target_total_68_jenis"] / float(FALLBACK_TARGET_RATIO)
812
 
813
+ # faktor
814
  base_n["faktor_penyesuaian_jenis"] = [
815
  faktor_penyesuaian_total(n, t)
816
  for n, t in zip(