irhamni commited on
Commit
dca404b
·
verified ·
1 Parent(s): cf45c75

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +98 -98
app.py CHANGED
@@ -1053,153 +1053,153 @@ def build_agg_wilayah_total_from_jenis(agg_jenis: pd.DataFrame, faktor_wilayah_j
1053
 
1054
  # ============================================================
1055
  # 9) SUMMARY (PER JENIS) + KESELURUHAN
1056
- # Ringkasan harus memuat Pop/Target68/Terkumpul/Coverage + Penyesuaian
 
 
1057
  # ============================================================
1058
 
1059
- def build_summary_per_jenis(agg_jenis: pd.DataFrame, agg_total: pd.DataFrame, faktor_wilayah_jenis: pd.DataFrame):
1060
  jenis_list = ["sekolah", "umum", "khusus"]
1061
 
1062
- def _row_default(j):
1063
  return {
1064
- "Jenis": j,
1065
  "Jumlah_Wilayah": 0,
1066
  "Total_Perpus": 0,
1067
 
 
1068
  "Pop_Total_Jenis": 0,
1069
  "Target68_Total_Jenis": 0,
1070
  "Terkumpul_Jenis": 0,
1071
  "Coverage_Target68_Jenis_%": 0.0,
1072
 
1073
- "Rata2_sub_koleksi": 0.0,
1074
- "Rata2_sub_sdm": 0.0,
1075
- "Rata2_sub_pelayanan": 0.0,
1076
- "Rata2_sub_pengelolaan": 0.0,
1077
- "Rata2_dim_kepatuhan": 0.0,
1078
- "Rata2_dim_kinerja": 0.0,
1079
-
1080
  "Indeks_Dasar_0_100": 0.0,
1081
  "Indeks_Final_Disesuaikan_0_100": 0.0,
1082
  "Penyesuaian_Poin": 0.0,
1083
  }
1084
 
1085
- rows_by = {j: _row_default(j) for j in jenis_list}
1086
 
1087
- # 1) isi indeks & subdimensi dari agg_jenis
1088
  if agg_jenis is not None and not agg_jenis.empty:
1089
  a = agg_jenis.copy()
1090
  a["Jenis"] = a["Jenis"].astype(str).str.lower().str.strip()
1091
 
1092
- for j in jenis_list:
1093
- sub = a[a["Jenis"] == j].copy()
 
 
 
 
 
 
 
 
 
 
 
1094
  if sub.empty:
1095
  continue
1096
 
1097
- dasar = float(pd.to_numeric(sub.get("Indeks_Dasar_Agregat_0_100", 0), errors="coerce").fillna(0).mean())
1098
- final = float(pd.to_numeric(sub.get("Indeks_Final_Agregat_0_100", 0), errors="coerce").fillna(0).mean())
1099
-
1100
- rows_by[j].update({
1101
- "Jumlah_Wilayah": int(sub.shape[0]),
1102
- "Total_Perpus": int(pd.to_numeric(sub.get("Jumlah", 0), errors="coerce").fillna(0).sum()),
1103
-
1104
- "Rata2_sub_koleksi": float(pd.to_numeric(sub.get("Rata2_sub_koleksi", 0), errors="coerce").fillna(0).mean()),
1105
- "Rata2_sub_sdm": float(pd.to_numeric(sub.get("Rata2_sub_sdm", 0), errors="coerce").fillna(0).mean()),
1106
- "Rata2_sub_pelayanan": float(pd.to_numeric(sub.get("Rata2_sub_pelayanan", 0), errors="coerce").fillna(0).mean()),
1107
- "Rata2_sub_pengelolaan": float(pd.to_numeric(sub.get("Rata2_sub_pengelolaan", 0), errors="coerce").fillna(0).mean()),
1108
- "Rata2_dim_kepatuhan": float(pd.to_numeric(sub.get("Rata2_dim_kepatuhan", 0), errors="coerce").fillna(0).mean()),
1109
- "Rata2_dim_kinerja": float(pd.to_numeric(sub.get("Rata2_dim_kinerja", 0), errors="coerce").fillna(0).mean()),
1110
-
1111
- "Indeks_Dasar_0_100": dasar,
1112
- "Indeks_Final_Disesuaikan_0_100": final,
1113
- "Penyesuaian_Poin": final - dasar,
1114
- })
1115
-
1116
- # 2) isi Pop/Target/Terkumpul dari faktor_wilayah_jenis (ini kunci KHUSUS match Excel)
1117
- if faktor_wilayah_jenis is not None and not faktor_wilayah_jenis.empty:
1118
- fw = faktor_wilayah_jenis.copy()
1119
- fw["Jenis"] = fw["Jenis"].astype(str).str.lower().str.strip()
1120
-
1121
- for j in jenis_list:
1122
- sub = fw[fw["Jenis"] == j].copy()
1123
- if sub.empty:
1124
- continue
1125
-
1126
- pop = int(pd.to_numeric(sub.get("pop_total_jenis", 0), errors="coerce").fillna(0).sum())
1127
- tgt = int(pd.to_numeric(sub.get("target_total_68_jenis", 0), errors="coerce").fillna(0).sum())
1128
- terk = int(pd.to_numeric(sub.get("n_jenis", 0), errors="coerce").fillna(0).sum())
1129
- cov = (terk / tgt * 100.0) if tgt > 0 else 0.0
1130
-
1131
- rows_by[j].update({
1132
- "Pop_Total_Jenis": pop,
1133
- "Target68_Total_Jenis": tgt,
1134
- "Terkumpul_Jenis": terk,
1135
- "Coverage_Target68_Jenis_%": cov,
1136
- })
1137
 
1138
- # 3) susun 3 jenis + keseluruhan (avg3 untuk indeks & subdim, TOTAL untuk pop/target/terkumpul)
1139
- rows = [rows_by[j] for j in jenis_list]
1140
 
1141
- def _avg3(field):
1142
- return (float(rows_by["sekolah"][field]) + float(rows_by["umum"][field]) + float(rows_by["khusus"][field])) / 3.0
 
1143
 
1144
- pop_all = int(rows_by["sekolah"]["Pop_Total_Jenis"] + rows_by["umum"]["Pop_Total_Jenis"] + rows_by["khusus"]["Pop_Total_Jenis"])
1145
- tgt_all = int(rows_by["sekolah"]["Target68_Total_Jenis"] + rows_by["umum"]["Target68_Total_Jenis"] + rows_by["khusus"]["Target68_Total_Jenis"])
1146
- terk_all = int(rows_by["sekolah"]["Terkumpul_Jenis"] + rows_by["umum"]["Terkumpul_Jenis"] + rows_by["khusus"]["Terkumpul_Jenis"])
1147
- cov_all = (terk_all / tgt_all * 100.0) if tgt_all > 0 else 0.0
1148
 
1149
- total_perpus_all = int(rows_by["sekolah"]["Total_Perpus"] + rows_by["umum"]["Total_Perpus"] + rows_by["khusus"]["Total_Perpus"])
1150
- jumlah_wilayah_all = int(agg_total.shape[0]) if (agg_total is not None and not agg_total.empty) else int(max(rows_by["sekolah"]["Jumlah_Wilayah"], rows_by["umum"]["Jumlah_Wilayah"], rows_by["khusus"]["Jumlah_Wilayah"]))
1151
 
1152
- dasar_all = _avg3("Indeks_Dasar_0_100")
1153
- final_all = _avg3("Indeks_Final_Disesuaikan_0_100")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1154
 
1155
  rows.append({
1156
  "Jenis": "keseluruhan",
1157
  "Jumlah_Wilayah": jumlah_wilayah_all,
1158
- "Total_Perpus": total_perpus_all,
1159
 
1160
  "Pop_Total_Jenis": pop_all,
1161
- "Target68_Total_Jenis": tgt_all,
1162
- "Terkumpul_Jenis": terk_all,
1163
- "Coverage_Target68_Jenis_%": cov_all,
1164
-
1165
- "Rata2_sub_koleksi": _avg3("Rata2_sub_koleksi"),
1166
- "Rata2_sub_sdm": _avg3("Rata2_sub_sdm"),
1167
- "Rata2_sub_pelayanan": _avg3("Rata2_sub_pelayanan"),
1168
- "Rata2_sub_pengelolaan": _avg3("Rata2_sub_pengelolaan"),
1169
- "Rata2_dim_kepatuhan": _avg3("Rata2_dim_kepatuhan"),
1170
- "Rata2_dim_kinerja": _avg3("Rata2_dim_kinerja"),
1171
-
1172
- "Indeks_Dasar_0_100": dasar_all,
1173
- "Indeks_Final_Disesuaikan_0_100": final_all,
1174
- "Penyesuaian_Poin": final_all - dasar_all,
1175
  })
1176
 
1177
  out = pd.DataFrame(rows)
1178
 
1179
- # display rounding
1180
- int_cols = ["Jumlah_Wilayah", "Total_Perpus", "Pop_Total_Jenis", "Target68_Total_Jenis", "Terkumpul_Jenis"]
1181
- for c in int_cols:
1182
  if c in out.columns:
1183
  out[c] = pd.to_numeric(out[c], errors="coerce").fillna(0).round(0).astype(int)
1184
 
1185
- for c in ["Coverage_Target68_Jenis_%"]:
1186
- if c in out.columns:
1187
- out[c] = pd.to_numeric(out[c], errors="coerce").fillna(0.0).round(2)
1188
-
1189
- for c in [
1190
- "Rata2_sub_koleksi","Rata2_sub_sdm","Rata2_sub_pelayanan","Rata2_sub_pengelolaan",
1191
- "Rata2_dim_kepatuhan","Rata2_dim_kinerja"
1192
- ]:
1193
- if c in out.columns:
1194
- out[c] = pd.to_numeric(out[c], errors="coerce").fillna(0.0).round(3)
1195
-
1196
- for c in ["Indeks_Dasar_0_100","Indeks_Final_Disesuaikan_0_100","Penyesuaian_Poin"]:
1197
  if c in out.columns:
1198
- out[c] = pd.to_numeric(out[c], errors="coerce").fillna(0.0).round(2)
 
 
 
1199
 
1200
  return out
1201
 
1202
 
 
1203
  # ============================================================
1204
  # 10) DETAIL ENTITAS: Final menempel dari agg_total (wilayah)
1205
  # ============================================================
 
1053
 
1054
  # ============================================================
1055
  # 9) SUMMARY (PER JENIS) + KESELURUHAN
1056
+ # - Ringkasan selalu 4 baris: sekolah, umum, khusus, keseluruhan
1057
+ # - Pop/Target/Terkumpul/Coverage diisi per jenis (SUM lintas wilayah)
1058
+ # - Keseluruhan: indeks = avg3 (tetap ÷3), Pop/Target/Terkumpul = SUM 3 jenis
1059
  # ============================================================
1060
 
1061
+ def build_summary_per_jenis(agg_jenis: pd.DataFrame, agg_total: pd.DataFrame):
1062
  jenis_list = ["sekolah", "umum", "khusus"]
1063
 
1064
+ def _row_default(jenis):
1065
  return {
1066
+ "Jenis": jenis,
1067
  "Jumlah_Wilayah": 0,
1068
  "Total_Perpus": 0,
1069
 
1070
+ # === POP/TARGET/TERKUMPUL/COVERAGE (PER JENIS) ===
1071
  "Pop_Total_Jenis": 0,
1072
  "Target68_Total_Jenis": 0,
1073
  "Terkumpul_Jenis": 0,
1074
  "Coverage_Target68_Jenis_%": 0.0,
1075
 
1076
+ # === NILAI INDEKS (PER JENIS) ===
 
 
 
 
 
 
1077
  "Indeks_Dasar_0_100": 0.0,
1078
  "Indeks_Final_Disesuaikan_0_100": 0.0,
1079
  "Penyesuaian_Poin": 0.0,
1080
  }
1081
 
1082
+ rows_by_jenis = {j: _row_default(j) for j in jenis_list}
1083
 
 
1084
  if agg_jenis is not None and not agg_jenis.empty:
1085
  a = agg_jenis.copy()
1086
  a["Jenis"] = a["Jenis"].astype(str).str.lower().str.strip()
1087
 
1088
+ # pastikan kolom numeric aman
1089
+ for c in [
1090
+ "Jumlah",
1091
+ "Indeks_Dasar_Agregat_0_100",
1092
+ "Indeks_Final_Agregat_0_100",
1093
+ "pop_total_jenis",
1094
+ "target_total_68_jenis",
1095
+ ]:
1096
+ if c in a.columns:
1097
+ a[c] = pd.to_numeric(a[c], errors="coerce").fillna(0)
1098
+
1099
+ for jenis in jenis_list:
1100
+ sub = a[a["Jenis"] == jenis].copy()
1101
  if sub.empty:
1102
  continue
1103
 
1104
+ # jumlah wilayah = banyak baris wilayah untuk jenis tsb
1105
+ jumlah_wilayah = int(sub.shape[0])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1106
 
1107
+ # terkumpul = total entitas yang masuk (Jumlah per wilayah dijumlahkan)
1108
+ terkumpul = int(pd.to_numeric(sub.get("Jumlah", 0), errors="coerce").fillna(0).sum())
1109
 
1110
+ # POP & TARGET per jenis: SUM lintas wilayah
1111
+ pop_total = int(pd.to_numeric(sub.get("pop_total_jenis", 0), errors="coerce").fillna(0).sum())
1112
+ target68 = int(pd.to_numeric(sub.get("target_total_68_jenis", 0), errors="coerce").fillna(0).sum())
1113
 
1114
+ coverage = (terkumpul / target68 * 100.0) if target68 > 0 else 0.0
 
 
 
1115
 
1116
+ dasar = float(pd.to_numeric(sub.get("Indeks_Dasar_Agregat_0_100", 0), errors="coerce").fillna(0).mean())
1117
+ final = float(pd.to_numeric(sub.get("Indeks_Final_Agregat_0_100", 0), errors="coerce").fillna(0).mean())
1118
 
1119
+ rows_by_jenis[jenis] = {
1120
+ "Jenis": jenis,
1121
+ "Jumlah_Wilayah": jumlah_wilayah,
1122
+ "Total_Perpus": terkumpul,
1123
+
1124
+ "Pop_Total_Jenis": pop_total,
1125
+ "Target68_Total_Jenis": target68,
1126
+ "Terkumpul_Jenis": terkumpul,
1127
+ "Coverage_Target68_Jenis_%": float(coverage),
1128
+
1129
+ "Indeks_Dasar_0_100": float(dasar),
1130
+ "Indeks_Final_Disesuaikan_0_100": float(final),
1131
+ "Penyesuaian_Poin": float(final - dasar),
1132
+ }
1133
+
1134
+ # ===== susun 3 baris jenis =====
1135
+ rows = [rows_by_jenis[j] for j in jenis_list]
1136
+
1137
+ # ===== baris keseluruhan (FIX) =====
1138
+ # indeks keseluruhan = avg3 (tetap ÷3, missing=0)
1139
+ dasar_all = (rows_by_jenis["sekolah"]["Indeks_Dasar_0_100"]
1140
+ + rows_by_jenis["umum"]["Indeks_Dasar_0_100"]
1141
+ + rows_by_jenis["khusus"]["Indeks_Dasar_0_100"]) / 3.0
1142
+
1143
+ final_all = (rows_by_jenis["sekolah"]["Indeks_Final_Disesuaikan_0_100"]
1144
+ + rows_by_jenis["umum"]["Indeks_Final_Disesuaikan_0_100"]
1145
+ + rows_by_jenis["khusus"]["Indeks_Final_Disesuaikan_0_100"]) / 3.0
1146
+
1147
+ # Pop/Target/Terkumpul keseluruhan = SUM 3 jenis
1148
+ pop_all = int(rows_by_jenis["sekolah"]["Pop_Total_Jenis"]
1149
+ + rows_by_jenis["umum"]["Pop_Total_Jenis"]
1150
+ + rows_by_jenis["khusus"]["Pop_Total_Jenis"])
1151
+
1152
+ target_all = int(rows_by_jenis["sekolah"]["Target68_Total_Jenis"]
1153
+ + rows_by_jenis["umum"]["Target68_Total_Jenis"]
1154
+ + rows_by_jenis["khusus"]["Target68_Total_Jenis"])
1155
+
1156
+ terkumpul_all = int(rows_by_jenis["sekolah"]["Terkumpul_Jenis"]
1157
+ + rows_by_jenis["umum"]["Terkumpul_Jenis"]
1158
+ + rows_by_jenis["khusus"]["Terkumpul_Jenis"])
1159
+
1160
+ coverage_all = (terkumpul_all / target_all * 100.0) if target_all > 0 else 0.0
1161
+
1162
+ jumlah_wilayah_all = int(agg_total.shape[0]) if (agg_total is not None and not agg_total.empty) else int(
1163
+ max(rows_by_jenis["sekolah"]["Jumlah_Wilayah"],
1164
+ rows_by_jenis["umum"]["Jumlah_Wilayah"],
1165
+ rows_by_jenis["khusus"]["Jumlah_Wilayah"])
1166
+ )
1167
 
1168
  rows.append({
1169
  "Jenis": "keseluruhan",
1170
  "Jumlah_Wilayah": jumlah_wilayah_all,
1171
+ "Total_Perpus": terkumpul_all,
1172
 
1173
  "Pop_Total_Jenis": pop_all,
1174
+ "Target68_Total_Jenis": target_all,
1175
+ "Terkumpul_Jenis": terkumpul_all,
1176
+ "Coverage_Target68_Jenis_%": float(coverage_all),
1177
+
1178
+ "Indeks_Dasar_0_100": float(dasar_all),
1179
+ "Indeks_Final_Disesuaikan_0_100": float(final_all),
1180
+ "Penyesuaian_Poin": float(final_all - dasar_all),
 
 
 
 
 
 
 
1181
  })
1182
 
1183
  out = pd.DataFrame(rows)
1184
 
1185
+ # ===== formatting tampilan =====
1186
+ # integer columns
1187
+ for c in ["Jumlah_Wilayah", "Total_Perpus", "Pop_Total_Jenis", "Target68_Total_Jenis", "Terkumpul_Jenis"]:
1188
  if c in out.columns:
1189
  out[c] = pd.to_numeric(out[c], errors="coerce").fillna(0).round(0).astype(int)
1190
 
1191
+ # float columns
1192
+ for c in ["Coverage_Target68_Jenis_%", "Indeks_Dasar_0_100", "Indeks_Final_Disesuaikan_0_100", "Penyesuaian_Poin"]:
 
 
 
 
 
 
 
 
 
 
1193
  if c in out.columns:
1194
+ if c == "Coverage_Target68_Jenis_%":
1195
+ out[c] = pd.to_numeric(out[c], errors="coerce").fillna(0.0).round(2)
1196
+ else:
1197
+ out[c] = pd.to_numeric(out[c], errors="coerce").fillna(0.0).round(2)
1198
 
1199
  return out
1200
 
1201
 
1202
+
1203
  # ============================================================
1204
  # 10) DETAIL ENTITAS: Final menempel dari agg_total (wilayah)
1205
  # ============================================================