LAPORAN UJIAN TENGAH SEMESTER

Mata Kuliah Epidemiologi



Dosen Pengampu:

Dr. I Gede Nyoman Mindra Jaya, M.Si



Disusun oleh:
Mona Yola Lumban Raja (140610230081)



PROGRAM STUDI S-1 STATISTIKA
FAKULTAS MATEMATIKA DAN ILMU PENGETAHUAN ALAM
UNIVERSITAS PADJADJARAN
JATINANGOR


Tahun Akademik 2024/2025

BAB I. PENDAHULUAN

1.1 Latar Belakang

Tuberkulosis (TBC) merupakan salah satu penyakit menular yang masih menjadi tantangan kesehatan masyarakat global. Berdasarkan Global Tuberculosis Report 2024 (WHO), Indonesia menempati peringkat kedua tertinggi setelah India dengan kontribusi sekitar 10% dari total kasus dunia. Pada tahun 2023 diperkirakan terdapat 1,09 juta kasus TBC di Indonesia dengan 125 ribu kematian setiap tahunnya (WHO, 2024; Kementerian Kesehatan RI, 2024).

Meskipun terjadi kemajuan pengendalian dengan penurunan under-reporting dari 41% (2017) menjadi 16% (2023), capaian program belum mencapai target nasional. Inisiasi pengobatan TBC sensitif obat baru mencapai 81% (target 90%), sementara keberhasilan pengobatan TBC resisten obat hanya 58% (target 80%) (Kemenkes RI, 2024).

Provinsi Jawa Barat menjadi wilayah strategis dalam konteks ini. Dengan populasi sekitar 50 juta jiwa, Jawa Barat mencatat jumlah kasus TBC tertinggi di Indonesia, yaitu 229.683 kasus dengan crude prevalence rate 456,22 per 100.000 penduduk (Dinkes Jabar, 2024). Kota Cirebon memiliki prevalensi tertinggi (1.195,3 per 100.000), sedangkan terendah terdapat di Kabupaten Pangandaran (222,99 per 100.000).

Disparitas urban–rural tampak jelas: prevalensi di wilayah kota (772,19 per 100.000) lebih dari dua kali lipat dibanding kabupaten (371,46 per 100.000). Perbedaan ini menunjukkan pengaruh determinan sosial seperti kepadatan penduduk, kondisi perumahan, dan akses layanan kesehatan. Namun variasi antarwilayah perkotaan menandakan adanya faktor lokal spesifik seperti efektivitas program TBC dan karakteristik epidemiologis unik.

Oleh karena itu, analisis spasial dan epidemiologis diperlukan untuk memahami pola penyebaran dan faktor risiko TBC di Jawa Barat. Pendekatan ini diharapkan memberikan dasar empiris bagi kebijakan pengendalian berbasis wilayah guna mendukung target eliminasi TBC nasional tahun 2030.

1.2 Rumusan Masalah

  1. Apa faktor agent–host–environment yang berhubungan dengan kasus TBC di Jawa Barat?
  2. Bagaimana distribusi kasus TBC di setiap kabupaten/kota pada tahun 2024?
  3. Bagaimana pola spasial TBC berdasarkan faktor risiko sosial-ekonomi?
  4. Apa implikasi hasil penelitian terhadap kebijakan pengendalian TBC berbasis wilayah?

1.3 Tujuan Penelitian

  1. Mengidentifikasi faktor agent–host–environment yang berhubungan dengan kasus TBC.
  2. Menghitung ukuran epidemiologi (prevalensi total dan per wilayah).
  3. Menganalisis pola spasial kasus TBC dengan uji Moran’s I dan LISA.
  4. Menguji hubungan antara faktor sosial-ekonomi dengan prevalensi TBC.
  5. Memberikan rekomendasi kebijakan pengendalian TBC berbasis bukti dan karakteristik lokal.

1.4 Batasan Penelitian

  1. Ruang lingkup terbatas pada kabupaten/kota di Provinsi Jawa Barat tahun 2024.
  2. Analisis bersifat deskriptif–asosiatif tanpa uji kausalitas.
  3. Variabel terbatas pada indikator sosial-ekonomi wilayah (kepadatan, kemiskinan, perumahan).
  4. Tidak mencakup faktor klinis individu (HIV, diabetes, perilaku).
  5. Menggunakan data agregat sehingga berpotensi ecological fallacy.

BAB II. TINJAUAN PUSTAKA

2.1 Tuberkulosis (TBC)

Tuberkulosis (TBC) merupakan penyakit infeksi menular yang disebabkan oleh Mycobacterium tuberculosis, bakteri berbentuk batang tahan asam (acid-fast bacilli). Penularan terjadi melalui droplet udara yang dihasilkan saat penderita TBC paru batuk atau bersin (WHO, 2024). Tidak semua individu yang terinfeksi akan sakit; hanya sekitar 5–10% yang berkembang menjadi TBC aktif, terutama ketika sistem imun melemah (Pai et al., 2016).

Secara global, TBC masih menjadi penyebab utama kematian akibat penyakit infeksi tunggal dengan 10,8 juta kasus baru dan 1,3 juta kematian pada tahun 2023 (WHO, 2024). Indonesia menempati peringkat kedua tertinggi di dunia setelah India, dengan sekitar 1,09 juta kasus dan 125 ribu kematian setiap tahun (Kemenkes RI, 2024).

Faktor risiko utama meliputi ko-infeksi HIV, diabetes mellitus, malnutrisi, perilaku merokok, serta kondisi sosial ekonomi rendah yang memperburuk akses terhadap layanan kesehatan.

2.2 Triad Epidemiologi

Model triad epidemiologi (Gordis, 2014) menjelaskan bahwa terjadinya penyakit merupakan hasil interaksi antara tiga komponen:

  • Agent: M. tuberculosis sebagai agen penyebab yang dapat bertahan di udara dan menjadi sumber infeksi.
  • Host: Individu dengan imunitas rendah, penyakit kronis, atau malnutrisi.
  • Environment: Kondisi fisik (ventilasi, pencahayaan) dan sosial (kemiskinan, kepadatan penduduk) yang mendukung penularan.

Ketiga faktor tersebut saling memengaruhi dan menentukan risiko penularan TBC (Rothman et al., 2008).

2.3 Ukuran Epidemiologi

Ukuran epidemiologi digunakan untuk menggambarkan besarnya beban penyakit dan menentukan prioritas intervensi kesehatan (Gordis, 2014).

2.3.1 Crude Prevalence Rate (CPR)

Mengukur proporsi total kasus dalam populasi tanpa mempertimbangkan karakteristik demografis:

\[ CPR = \frac{\text{Total Kasus}}{\text{Total Populasi}} \times 100.000 \]

CPR digunakan untuk membandingkan beban penyakit antarwilayah.

2.3.2 Prevalensi (Period Prevalence)

Menunjukkan proporsi penduduk yang menderita TBC selama periode tertentu:

\[ \text{Prevalensi} = \frac{\text{Jumlah Kasus TBC (2024)}}{\text{Jumlah Penduduk (2024)}} \times 100.000 \]

Prevalensi menggambarkan total beban penyakit (kasus lama + baru).

2.3.3 Attack Rate (AR)

Menggambarkan proporsi populasi yang terserang penyakit dalam periode tertentu:

\[ \text{Attack Rate} = \frac{\text{Jumlah Kasus TBC (2024)}}{\text{Jumlah Penduduk (2024)}} \times 100\% \]

AR digunakan untuk melihat risiko penularan di suatu wilayah.

2.4 Faktor Risiko TBC

Beberapa determinan sosial dan lingkungan yang berpengaruh terhadap penyebaran TBC meliputi:

Faktor Risiko Dampak terhadap TBC
Kepadatan penduduk Meningkatkan frekuensi kontak antarindividu
Kemiskinan Membatasi akses layanan kesehatan dan memperburuk gizi
Rumah tidak layak huni Ventilasi buruk dan kelembaban tinggi memudahkan penularan
Status sosial ekonomi Pendidikan dan penghasilan rendah meningkatkan kerentanan

2.5 Analisis Spasial dalam Epidemiologi

Analisis spasial digunakan untuk memahami pola penyebaran penyakit dan mengidentifikasi area prioritas intervensi (Pfeiffer et al., 2008).

  • Moran’s I: Mengukur autokorelasi spasial global; nilai positif menunjukkan pengelompokan (clustering), sedangkan nilai mendekati nol menunjukkan pola acak (Anselin, 1995).
  • LISA: Mengidentifikasi klaster lokal (hotspot dan coldspot) di tingkat wilayah.
  • Matriks Bobot Spasial (W): Menentukan kedekatan antarwilayah menggunakan metode Queen contiguity.

2.6 Desain Studi Epidemiologi

Penelitian ini menggunakan desain studi ekologi dengan pendekatan deskriptif kuantitatif.
Unit analisis adalah kabupaten/kota di Jawa Barat tahun 2024.

Kelebihan: efisien, menggunakan data sekunder, dan mampu menggambarkan pola geografis.
Keterbatasan: tidak dapat mengidentifikasi hubungan kausal individual (ecological fallacy) (Morgenstern, 1995).

2.7 Kerangka Konseptual Penelitian

Kerangka konseptual menggambarkan hubungan antara triad epidemiologi, faktor sosial-ekonomi wilayah, mekanisme transmisi, prevalensi TBC, serta analisis spasial. Hasil analisis ini menjadi dasar perumusan kebijakan pengendalian TBC berbasis wilayah.

Gambar 2.1 Kerangka Konseptual Penelitian
Gambar 2.1 Kerangka Konseptual Penelitian

Gambar 2.1. Kerangka Konseptual Analisis Epidemiologis Kasus TBC di Jawa Barat Tahun 2024.
Kode R untuk menghasilkan diagram ini disajikan di Lampiran 1.

BAB III. METODOLOGI PENELITIAN

3.1 Desain Penelitian

Penelitian ini menggunakan studi ekologi deskriptif kuantitatif, dengan unit analisis wilayah administratif tingkat kabupaten/kota di Provinsi Jawa Barat tahun 2024. Tujuannya adalah menggambarkan hubungan antara faktor sosial-ekonomi dan kepadatan penduduk dengan kasus Tuberkulosis (TBC).

3.2 Jenis dan Sumber Data

Data bersifat sekunder dan diperoleh dari: - Open Data Jawa Barat: jumlah kasus TBC (2024) - Badan Pusat Statistik (BPS): data demografi dan sosial ekonomi - GADM Indonesia Level 2: shapefile batas administratif

Pra-pengolahan data meliputi: penyamaan nama wilayah, pemeriksaan data kosong/outlier, serta validasi konsistensi antar sumber. Wilayah non-administratif (Waduk Cirata) dikeluarkan dari analisis.

Variabel Keterangan Jenis
Jumlah Penduduk Populasi per kabupaten/kota Kuantitatif
Rumah Layak Huni (%) Proporsi rumah tangga layak huni Kuantitatif
Penduduk Miskin (%) Persentase penduduk miskin Kuantitatif
Kasus TBC Total kasus TBC tahun 2024 Kuantitatif
Kepadatan Penduduk Jumlah penduduk/km² Kuantitatif

3.3 Populasi dan Sampel Penelitian

Populasi mencakup 27 kabupaten/kota di Jawa Barat, namun satu wilayah (Waduk Cirata) dikeluarkan, sehingga jumlah sampel 26 wilayah.
Teknik yang digunakan adalah total sampling, dengan kriteria inklusi: wilayah administratif resmi dan memiliki data lengkap tahun 2024.

3.4 Ukuran Epidemiologi

Penelitian ini menghitung dua indikator utama: prevalensi tahunan dan attack rate (AR).

Prevalensi

\[ \text{Prevalensi} = \frac{\text{Kasus TBC (2024)}}{\text{Penduduk (2024)}} \times 100.000 \]

Menggambarkan beban penyakit TBC per 100.000 penduduk.

Attack Rate

\[ \text{Attack Rate} = \frac{\text{Kasus TBC (2024)}}{\text{Penduduk (2024)}} \times 100\% \]

Menunjukkan proporsi penduduk yang mengalami TBC selama satu tahun.

3.5 Teknik Analisis Data

Analisis dilakukan dengan R 4.3.3 menggunakan paket dplyr, ggplot2, sf, tmap, dan spdep.

a. Analisis Deskriptif

Menggambarkan karakteristik wilayah berdasarkan prevalensi TBC, kepadatan, dan kemiskinan melalui tabel, boxplot, dan peta tematik.

b. Analisis Korelasi

Hubungan antar variabel diuji menggunakan korelasi Spearman karena data tidak berdistribusi normal.
Kriteria kekuatan korelasi (Dancey & Reidy, 2007):
|r| < 0,3 (lemah), 0,3–0,5 (sedang), 0,5–0,7 (kuat); α = 0,05.

c. Analisis Spasial

1. Moran’s I (Autokorelasi Global): \[ I = \frac{n}{\sum_i\sum_j w_{ij}} \frac{\sum_i\sum_j w_{ij}(x_i - \bar{x})(x_j - \bar{x})} {\sum_i(x_i - \bar{x})^2} \] - I > 0: clustering
- I ≈ 0: acak
- I < 0: dispersi

2. LISA (Autokorelasi Lokal):
Menentukan klaster High-High (hotspot) dan Low-Low (coldspot).
Matriks bobot spasial menggunakan Queen Contiguity, karena lebih merepresentasikan hubungan antarwilayah yang berbatasan secara sisi maupun sudut.

d. Visualisasi dan Dashboard

Hasil analisis divisualisasikan dalam dashboard interaktif R Shiny, yang menampilkan peta, filter wilayah, serta ringkasan indikator epidemiologi.

3.6 Alur Penelitian

Tahapan penelitian meliputi:
1. Studi Literatur & Identifikasi Masalah
2. Pengumpulan Data Sekunder (Oktober 2024)
3. Pembersihan dan Penggabungan Data
4. Analisis Deskriptif, Korelasi, dan Spasial
5. Pembuatan Peta & Dashboard (November 2024)
6. Interpretasi dan Penyusunan Laporan Akhir

Gambar 3.1 Alur Penelitian
Gambar 3.1 Alur Penelitian

3.7 Aspek Etika Penelitian

Penelitian ini menggunakan data publik tanpa identitas individu sehingga tidak memerlukan ethical clearance. Prinsip etika tetap dijaga melalui: 1. Integritas data (tanpa manipulasi) 2. Transparansi sumber 3. Replikasi kode analisis (R script) 4. Pengakuan penggunaan AI (ChatGPT) dalam proses penulisan dan dokumentasi.

3.8 Batasan Penelitian

  1. Data hanya mencakup tahun 2024 sehingga tidak menggambarkan tren waktu.
  2. Analisis dilakukan pada level agregat (kabupaten/kota) sehingga tidak dapat menilai hubungan sebab-akibat individu (ecological fallacy).
  3. Faktor risiko individu (HIV, gizi, perilaku) tidak termasuk dalam model.

BAB IV. HASIL DAN PEMBAHASAN

Bab ini menyajikan hasil analisis epidemiologis kasus tuberkulosis (TBC) di Provinsi Jawa Barat tahun 2024. Analisis mencakup statistik deskriptif, identifikasi wilayah dengan beban penyakit tertinggi, analisis korelasi faktor risiko, serta analisis spasial untuk memahami pola sebaran geografis kasus TBC.

4.1 Statistik Deskriptif

4.1.1 Ringkasan Umum

Analisis deskriptif memberikan gambaran awal tentang karakteristik sebaran kasus TBC di Jawa Barat.

# Statistik deskriptif
summary_stats <- data_tbc %>%
  summarise(
    Jumlah_Wilayah = n(),
    Total_Penduduk = sum(Jumlah_Penduduk, na.rm = TRUE),
    Total_Kasus = sum(Jumlah_Kasus_TBC, na.rm = TRUE),
    Mean_Prevalensi = mean(Prevalensi_per_100k, na.rm = TRUE),
    Median_Prevalensi = median(Prevalensi_per_100k, na.rm = TRUE),
    SD_Prevalensi = sd(Prevalensi_per_100k, na.rm = TRUE),
    Min_Prevalensi = min(Prevalensi_per_100k, na.rm = TRUE),
    Max_Prevalensi = max(Prevalensi_per_100k, na.rm = TRUE),
    Range_Prevalensi = Max_Prevalensi - Min_Prevalensi
  )

# Tampilkan tabel
kable(summary_stats,
      digits = 2,
      caption = "Tabel 4.1 Statistik Deskriptif Kasus TBC di Jawa Barat 2024",
      col.names = c("Jumlah Wilayah", "Total Penduduk", "Total Kasus", 
                    "Mean", "Median", "SD", "Min", "Max", "Range"),
      format.args = list(big.mark = ",")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), 
                full_width = FALSE, position = "center") %>%
  add_header_above(c(" " = 3, "Prevalensi per 100.000 Penduduk" = 6))
Tabel 4.1 Statistik Deskriptif Kasus TBC di Jawa Barat 2024
Prevalensi per 100.000 Penduduk
Jumlah Wilayah Total Penduduk Total Kasus Mean Median SD Min Max Range
27 50,345,190 229,683 505.03 438.86 251.1 222.99 1,195.3 972.31

Interpretasi: Berdasarkan Tabel 4.1, Provinsi Jawa Barat dengan populasi sekitar 50 juta jiwa mencatat jumlah kasus TBC yang tinggi pada tahun 2024. Rata-rata prevalensi TBC tercatat sebesar 505.03 per 100.000 penduduk dengan simpangan baku 251.1, menunjukkan variasi yang cukup besar antarwilayah. Nilai terendah mencapai 222.99 dan tertinggi 1195.3 per 100.000 penduduk. Perbedaan antara mean dan median menunjukkan distribusi data yang tidak simetris (skewed), sedangkan rentang nilai yang lebar mengindikasikan adanya disparitas beban penyakit yang signifikan. Temuan ini menegaskan perlunya strategi pengendalian TBC berbasis wilayah yang mempertimbangkan kondisi sosial-ekonomi lokal.

4.1.2 Distribusi Berdasarkan Tipe Wilayah

library(dplyr)
library(knitr)
library(kableExtra)
library(ggplot2)
library(readr)

# Load dan preprocessing data LENGKAP
data_tbc <- read_delim("C:\\Users\\ASUS\\Downloads\\Data Epidemiologi.csv",
                       show_col_types = FALSE) %>%
  rename(
    Kabupaten_Kota = `KABUPATEN/KOTA`,
    Jumlah_Penduduk = `Jumlah Penduduk `,
    Rumah_Layak_Huni = `Rumah Layak Huni%`,
    Persen_Penduduk_Miskin = `Persentase Penduduk Miskin%`,
    Jumlah_Kasus_TBC = `Jumlah Kasus TBC`,
    Kepadatan_Penduduk = `Kepadatan Penduduk (Jiwa/KM2)`
  ) %>%
  mutate(
    Prevalensi_per_100k = (Jumlah_Kasus_TBC / Jumlah_Penduduk) * 100000,
    Tipe_Wilayah = ifelse(grepl("KOTA", Kabupaten_Kota), "Kota", "Kabupaten"),
    Attack_Rate = (Jumlah_Kasus_TBC / Jumlah_Penduduk) * 100,
    Kategori_Prevalensi = case_when(
      Prevalensi_per_100k >= 500 ~ "Sangat Tinggi",
      Prevalensi_per_100k >= 400 ~ "Tinggi",
      Prevalensi_per_100k >= 300 ~ "Sedang",
      TRUE ~ "Rendah"
    )
  )
# Cek distribusi tipe wilayah
table(data_tbc$Tipe_Wilayah)
## 
## Kabupaten      Kota 
##        18         9
# Statistik berdasarkan tipe wilayah
stats_by_type <- data_tbc %>%
  group_by(Tipe_Wilayah) %>%
  summarise(
    Jumlah = n(),
    Total_Penduduk = sum(Jumlah_Penduduk),
    Total_Kasus = sum(Jumlah_Kasus_TBC),
    Mean_Prevalensi = mean(Prevalensi_per_100k),
    Median_Prevalensi = median(Prevalensi_per_100k),
    SD_Prevalensi = sd(Prevalensi_per_100k)
  )

# Buat tabel
kable(stats_by_type,
      digits = 2,
      caption = "Tabel 4.2 Perbandingan Prevalensi TBC: Kabupaten vs Kota",
      col.names = c("Tipe", "Jumlah", "Populasi", "Kasus", 
                    "Mean", "Median", "SD"),
      format.args = list(big.mark = ",")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), 
                full_width = FALSE, position = "center") %>%
  add_header_above(c(" " = 4, "Prevalensi per 100.000" = 3))
Tabel 4.2 Perbandingan Prevalensi TBC: Kabupaten vs Kota
Prevalensi per 100.000
Tipe Jumlah Populasi Kasus Mean Median SD
Kabupaten 18 39,661,170 159,252 371.46 361.79 92.30
Kota 9 10,684,020 70,431 772.19 736.78 257.62

Interpretasi: Interpretasi: Berdasarkan Tabel 4.2, terlihat bahwa wilayah kota memiliki rata-rata prevalensi TBC yang jauh lebih tinggi dibandingkan kabupaten (772,19 vs 371,46 per 100.000 penduduk). Kondisi ini menunjukkan bahwa urbanisasi dan kepadatan penduduk berperan penting dalam mempercepat transmisi penyakit. Standar deviasi yang tinggi pada wilayah kota (257,62) menandakan adanya variasi yang cukup besar antar kota dalam beban penyakit. Meskipun jumlah kabupaten lebih banyak, kontribusi kasus dari wilayah kota mencapai 30,7% dari total kasus TBC di Jawa Barat. Hasil ini sejalan dengan temuan Harling & Castro (2014) yang menyatakan bahwa wilayah dengan kepadatan tinggi memiliki risiko penularan TBC sekitar 1,5–2 kali lebih besar dibandingkan wilayah rural. Dengan demikian, faktor urbanisasi dan kepadatan penduduk menjadi determinan utama dalam penyebaran TBC di Jawa Barat.

Untuk memvisualisasikan perbedaan distribusi ini, disajikan boxplot perbandingan prevalensi antara kabupaten dan kota (Gambar 4.1):

# Visualisasi boxplot
ggplot(data_tbc, aes(x = Tipe_Wilayah, y = Prevalensi_per_100k, fill = Tipe_Wilayah)) +
  geom_boxplot(alpha = 0.7, outlier.colour = "red", outlier.shape = 16, outlier.size = 3) +
  geom_jitter(width = 0.2, alpha = 0.5, size = 2) +
  scale_fill_manual(values = c("Kabupaten" = "#E63946", "Kota" = "#457B9D")) +
  labs(title = "Distribusi Prevalensi TBC: Kabupaten vs Kota",
       subtitle = "Jawa Barat 2024",
       x = "Tipe Wilayah",
       y = "Prevalensi per 100.000 Penduduk",
       caption = "Titik merah menunjukkan outlier") +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
        plot.subtitle = element_text(hjust = 0.5, size = 11),
        legend.position = "none") +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 4, 
               fill = "yellow", color = "black")

Gambar 4.1 Boxplot menunjukkan median (garis tengah kotak), kuartil 1 dan 3 (batas kotak), serta outlier (titik merah). Titik berlian kuning menunjukkan nilai rata-rata. Terlihat bahwa wilayah kota memiliki median dan variasi prevalensi yang lebih tinggi.

4.1.3 Tabel Lengkap Prevalensi Seluruh Wilayah

library(ggplot2)
# Buat kolom Kategori_Prevalensi dulu
data_tbc <- data_tbc %>%
  mutate(
    Kategori_Prevalensi = case_when(
      Prevalensi_per_100k >= 500 ~ "Sangat Tinggi",
      Prevalensi_per_100k >= 400 ~ "Tinggi",
      Prevalensi_per_100k >= 300 ~ "Sedang",
      TRUE ~ "Rendah"
    )
  )

# Tabel lengkap dengan urutan prevalensi tertinggi
# Pakai nama kolom yang BARU
tabel_prev <- data_tbc %>%
  select(Kabupaten_Kota, Tipe_Wilayah, Jumlah_Penduduk, 
         Jumlah_Kasus_TBC, Prevalensi_per_100k, Kategori_Prevalensi) %>%
  arrange(desc(Prevalensi_per_100k))

kable(tabel_prev,
      caption = "Tabel 4.3 Prevalensi Kasus TBC per 100.000 Penduduk di Seluruh Wilayah Jawa Barat (2024)",
      digits = 2,
      col.names = c("Wilayah", "Tipe", "Populasi", "Kasus TBC", 
                    "Prevalensi/100k", "Kategori"),
      format.args = list(big.mark = ",")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE, font_size = 12) %>%
  row_spec(which(tabel_prev$Kategori_Prevalensi == "Sangat Tinggi"), 
           bold = TRUE, background = "#ffcccc") %>%
  row_spec(which(tabel_prev$Kategori_Prevalensi == "Tinggi"), 
           background = "#ffe0cc") %>%
  row_spec(which(tabel_prev$Kategori_Prevalensi == "Sedang"), 
           background = "#fff3cd")
Tabel 4.3 Prevalensi Kasus TBC per 100.000 Penduduk di Seluruh Wilayah Jawa Barat (2024)
Wilayah Tipe Populasi Kasus TBC Prevalensi/100k Kategori
KOTA CIREBON Kota 344,850 4,122 1,195.30 Sangat Tinggi
KOTA BOGOR Kota 1,078,350 11,418 1,058.84 Sangat Tinggi
KOTA SUKABUMI Kota 365,740 3,477 950.68 Sangat Tinggi
KOTA CIMAHI Kota 598,700 4,513 753.80 Sangat Tinggi
KOTA BANDUNG Kota 2,528,160 18,627 736.78 Sangat Tinggi
KOTA BANJAR Kota 209,790 1,519 724.06 Sangat Tinggi
KOTA TASIKMALAYA Kota 750,730 4,693 625.12 Sangat Tinggi
KABUPATEN KARAWANG Kabupaten 2,554,380 13,474 527.49 Sangat Tinggi
KOTA BEKASI Kota 2,644,060 13,640 515.87 Sangat Tinggi
KABUPATEN BOGOR Kabupaten 5,682,300 29,110 512.29 Sangat Tinggi
KABUPATEN BEKASI Kabupaten 3,273,870 15,458 472.16 Tinggi
KABUPATEN CIANJUR Kabupaten 2,584,990 12,197 471.84 Tinggi
KABUPATEN PURWAKARTA Kabupaten 1,050,340 4,687 446.24 Tinggi
KABUPATEN SUKABUMI Kabupaten 2,828,020 12,411 438.86 Tinggi
KABUPATEN CIREBON Kabupaten 2,387,960 9,587 401.47 Tinggi
KOTA DEPOK Kota 2,163,640 8,422 389.25 Sedang
KABUPATEN SUBANG Kabupaten 1,663,160 6,321 380.06 Sedang
KABUPATEN BANDUNG Kabupaten 3,753,120 14,012 373.34 Sedang
KABUPATEN GARUT Kabupaten 2,716,950 9,516 350.25 Sedang
KABUPATEN MAJALENGKA Kabupaten 1,352,540 4,517 333.96 Sedang
KABUPATEN KUNINGAN Kabupaten 1,213,930 4,045 333.22 Sedang
KABUPATEN SUMEDANG Kabupaten 1,187,130 3,930 331.05 Sedang
KABUPATEN INDRAMAYU Kabupaten 1,914,040 6,092 318.28 Sedang
KABUPATEN CIAMIS Kabupaten 1,259,230 3,477 276.12 Rendah
KABUPATEN TASIKMALAYA Kabupaten 1,920,920 4,881 254.10 Rendah
KABUPATEN BANDUNG BARAT Kabupaten 1,884,190 4,569 242.49 Rendah
KABUPATEN PANGANDARAN Kabupaten 434,100 968 222.99 Rendah

Tabel 4.3 menyajikan data lengkap prevalensi TBC untuk seluruh kabupaten/kota di Jawa Barat. Pewarnaan menunjukkan tingkat keparahan: merah tua (sangat tinggi), orange (tinggi), dan kuning (sedang).

4.2 Wilayah dengan Beban TBC Tertinggi

4.2.1 Sepuluh Wilayah dengan Prevalensi Tertinggi

Identifikasi wilayah dengan prevalensi tertinggi penting untuk penentuan prioritas intervensi.

library(dplyr)
library(knitr)
library(kableExtra)

# 10 wilayah dengan prevalensi tertinggi
top_prevalensi <- data_tbc %>%
  arrange(desc(Prevalensi_per_100k)) %>%
  select(Kabupaten_Kota, Tipe_Wilayah, Jumlah_Penduduk, 
         Jumlah_Kasus_TBC, Prevalensi_per_100k, Kepadatan_Penduduk) %>%
  head(10)

kable(top_prevalensi,
      digits = 2,
      col.names = c("Wilayah", "Tipe", "Populasi", "Kasus TBC",
                    "Prevalensi/100k", "Kepadatan (Jiwa/km²)"),
      caption = "Tabel 4.4 Sepuluh Wilayah dengan Angka Prevalensi TBC Tertinggi",
      format.args = list(big.mark = ",")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
  row_spec(1:3, bold = TRUE, background = "#ffcccc") %>%
  footnote(general = "Tiga wilayah teratas ditandai dengan warna merah",
           general_title = "Catatan:")
Tabel 4.4 Sepuluh Wilayah dengan Angka Prevalensi TBC Tertinggi
Wilayah Tipe Populasi Kasus TBC Prevalensi/100k Kepadatan (Jiwa/km²)
KOTA CIREBON Kota 344,850 4,122 1,195.30 9,036
KOTA BOGOR Kota 1,078,350 11,418 1,058.84 10,273
KOTA SUKABUMI Kota 365,740 3,477 950.68 766
KOTA CIMAHI Kota 598,700 4,513 753.80 13,716
KOTA BANDUNG Kota 2,528,160 18,627 736.78 15,557
KOTA BANJAR Kota 209,790 1,519 724.06 1,598
KOTA TASIKMALAYA Kota 750,730 4,693 625.12 4,191
KABUPATEN KARAWANG Kabupaten 2,554,380 13,474 527.49 1,365
KOTA BEKASI Kota 2,644,060 13,640 515.87 12,074
KABUPATEN BOGOR Kabupaten 5,682,300 29,110 512.29 1,942
Catatan:
Tiga wilayah teratas ditandai dengan warna merah

Interpretasi:

Tabel 4.4 menunjukkan bahwa Kota Cirebon memiliki prevalensi TBC tertinggi di Jawa Barat, hampir lima kali lipat lebih besar dibandingkan wilayah dengan prevalensi terendah.
Sebagian besar wilayah dengan prevalensi tinggi merupakan kota besar, memperkuat bukti bahwa daerah urban memiliki tingkat penularan lebih tinggi akibat kepadatan penduduk, kondisi perumahan yang kurang layak, serta kemiskinan. Faktor-faktor tersebut memperkuat peran komponen environment dalam triad epidemiologi, di mana kondisi sosial dan fisik yang padat meningkatkan risiko transmisi antarindividu.
Selain itu, wilayah dengan prevalensi tinggi umumnya memiliki kepadatan penduduk besar, meskipun hubungan ini tidak selalu linier (dibahas lebih lanjut pada bagian korelasi). Perlu dicatat pula bahwa beban absolut kasus di kabupaten berpenduduk besar, seperti Kabupaten Bogor, tetap tinggi meskipun prevalensinya relatif lebih rendah karena jumlah populasi yang besar.

# Visualisasi bar chart
ggplot(top_prevalensi, aes(x = reorder(Kabupaten_Kota, Prevalensi_per_100k), 
                           y = Prevalensi_per_100k, fill = Tipe_Wilayah)) +
  geom_bar(stat = "identity", width = 0.7) +
  geom_text(aes(label = round(Prevalensi_per_100k, 1)), 
            hjust = -0.2, size = 3.5, fontface = "bold") +
  coord_flip() +
  scale_fill_manual(values = c("Kabupaten" = "#E63946", "Kota" = "#457B9D")) +
  labs(title = "10 Wilayah dengan Prevalensi TBC Tertinggi",
       subtitle = "Provinsi Jawa Barat Tahun 2024",
       x = NULL,
       y = "Prevalensi per 100.000 Penduduk",
       fill = "Tipe Wilayah",
       caption = "Sumber: Dinas Kesehatan Provinsi Jawa Barat, 2024") +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
        plot.subtitle = element_text(hjust = 0.5, size = 11),
        axis.text.y = element_text(size = 10),
        legend.position = "bottom") +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15)))

Gambar 4.2 Bar chart horizontal memudahkan perbandingan prevalensi antar wilayah. Kota Cirebon jelas menonjol sebagai wilayah dengan beban TBC tertinggi.

4.2.2 Distribusi Kategori Prevalensi

# Hitung distribusi kategori
dist_kategori <- data_tbc %>%
  group_by(Kategori_Prevalensi) %>%
  summarise(
    Jumlah = n(),
    Persen = (n()/nrow(data_tbc))*100,
    Total_Kasus = sum(Jumlah_Kasus_TBC),
    Persen_Kasus = (Total_Kasus/sum(data_tbc$Jumlah_Kasus_TBC))*100
  ) %>%
  arrange(desc(Kategori_Prevalensi))

kable(dist_kategori,
      digits = 2,
      col.names = c("Kategori", "Jumlah Wilayah", "% Wilayah", 
                    "Total Kasus", "% Kasus"),
      caption = "Tabel 4.5 Distribusi Wilayah Berdasarkan Kategori Prevalensi",
      format.args = list(big.mark = ",")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Tabel 4.5 Distribusi Wilayah Berdasarkan Kategori Prevalensi
Kategori Jumlah Wilayah % Wilayah Total Kasus % Kasus
Tinggi 5 18.52 54,340 23.66
Sedang 8 29.63 56,855 24.75
Sangat Tinggi 10 37.04 104,593 45.54
Rendah 4 14.81 13,895 6.05
# Pie chart kategori
ggplot(dist_kategori, aes(x = "", y = Jumlah, fill = Kategori_Prevalensi)) +
  geom_bar(stat = "identity", width = 1, color = "white") +
  coord_polar("y", start = 0) +
  scale_fill_manual(values = c("Sangat Tinggi" = "#cb181d",
                               "Tinggi" = "#fb6a4a",
                               "Sedang" = "#fcae91",
                               "Rendah" = "#fee5d9")) +
  labs(title = "Distribusi Wilayah Berdasarkan Kategori Prevalensi TBC",
       subtitle = "Jawa Barat 2024",
       fill = "Kategori") +
  theme_void() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold", size = 13)) +
  geom_text(aes(label = paste0(Jumlah, " wilayah\n(", round(Persen, 1), "%)")),
            position = position_stack(vjust = 0.5), size = 3.5, fontface = "bold")

Gambar 4.3 Pie chart menunjukkan bahwa sebagian besar wilayah berada dalam kategori prevalensi sedang hingga tinggi, mengindikasikan bahwa TBC masih menjadi masalah kesehatan masyarakat yang luas di Jawa Barat.

4.3 Analisis Attack Rate

Attack rate menggambarkan proporsi penduduk yang mengalami penyakit dalam periode tertentu. Dalam konteks penelitian ini, attack rate dihitung sebagai pendekatan deskriptif tahunan.

library(dplyr)
library(knitr)
library(kableExtra)

# Buat kolom Attack_Rate dulu
data_tbc <- data_tbc %>%
  mutate(Attack_Rate = (Jumlah_Kasus_TBC / Jumlah_Penduduk) * 100)

# Hitung dan urutkan attack rate
top_attack <- data_tbc %>%
  arrange(desc(Attack_Rate)) %>%
  select(Kabupaten_Kota, Tipe_Wilayah, Jumlah_Penduduk, 
         Jumlah_Kasus_TBC, Attack_Rate, Prevalensi_per_100k) %>%
  head(10)

kable(top_attack,
      digits = 3,
      col.names = c("Wilayah", "Tipe", "Populasi", "Kasus TBC", 
                    "Attack Rate (%)", "Prevalensi/100k"),
      caption = "Tabel 4.6 Sepuluh Wilayah dengan Attack Rate Tertinggi (2024)",
      format.args = list(big.mark = ",")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
  row_spec(1:3, bold = TRUE, background = "#ffe0cc") %>%
  footnote(general = "Attack Rate = (Jumlah Kasus / Jumlah Penduduk) × 100%",
           general_title = "Formula:")
Tabel 4.6 Sepuluh Wilayah dengan Attack Rate Tertinggi (2024)
Wilayah Tipe Populasi Kasus TBC Attack Rate (%) Prevalensi/100k
KOTA CIREBON Kota 344,850 4,122 1.195 1,195.302
KOTA BOGOR Kota 1,078,350 11,418 1.059 1,058.840
KOTA SUKABUMI Kota 365,740 3,477 0.951 950.675
KOTA CIMAHI Kota 598,700 4,513 0.754 753.800
KOTA BANDUNG Kota 2,528,160 18,627 0.737 736.781
KOTA BANJAR Kota 209,790 1,519 0.724 724.057
KOTA TASIKMALAYA Kota 750,730 4,693 0.625 625.125
KABUPATEN KARAWANG Kabupaten 2,554,380 13,474 0.527 527.486
KOTA BEKASI Kota 2,644,060 13,640 0.516 515.873
KABUPATEN BOGOR Kabupaten 5,682,300 29,110 0.512 512.293
Formula:
Attack Rate = (Jumlah Kasus / Jumlah Penduduk) × 100%

Interpretasi:

  • Urutan wilayah dengan attack rate tertinggi sama dengan urutan prevalensi tertinggi karena keduanya mengukur proporsi kasus terhadap populasi (hanya beda skala: per 100 vs per 100.000)
  • Attack rate tertinggi di Kota Cirebon sebesar 1.2% berarti bahwa dalam 100 penduduk, terdapat sekitar 1.2 orang yang terdiagnosis TBC pada tahun 2024

4.4 Analisis Spasial TBC

Analisis spasial merupakan pendekatan penting dalam epidemiologi untuk memahami pola geografis penyebaran penyakit. Dalam konteks TBC, analisis spasial membantu mengidentifikasi: - Area dengan risiko tinggi (hotspot) - Pola pengelompokan kasus (clustering) - Hubungan spasial antar wilayah ### 4.4.1 Persiapan Data Spasial

library(sf)
library(tidyverse)
library(readxl)

# LOAD DATA TBC - PAKAI PATH LENGKAP, JANGAN PAKAI setwd()
data_tbc <- read_excel("C:/Users/ASUS/Documents/Dashboard_TBC_Jabar/Data/Data Epidemiologi.xlsx")

cat("📋 Data berhasil dimuat!\n")
## 📋 Data berhasil dimuat!
cat("Jumlah baris:", nrow(data_tbc), "\n\n")
## Jumlah baris: 27
# Baca shapefile - PAKAI PATH LENGKAP
jabar_shp <- st_read("C:/Users/ASUS/Documents/Dashboard_TBC_Jabar/Data/gadm41_IDN_2.shp", quiet = TRUE) %>%
  filter(NAME_1 == "Jawa Barat") %>%
  filter(NAME_2 != "Waduk Cirata") %>%
  mutate(NAME_2 = case_when(
    NAME_2 == "Banjar" ~ "Kota Banjar",
    NAME_2 == "Cimahi" ~ "Kota Cimahi",
    TRUE ~ NAME_2
  ))
# Harmonisasi nama wilayah - PAKAI NAMA KOLOM YANG BENAR
data_tbc <- data_tbc %>%
  mutate(
    Nama_Matching = case_when(
      # Kabupaten
      `KABUPATEN/KOTA` == "KABUPATEN BOGOR" ~ "Bogor",
      `KABUPATEN/KOTA` == "KABUPATEN SUKABUMI" ~ "Sukabumi",
      `KABUPATEN/KOTA` == "KABUPATEN CIANJUR" ~ "Cianjur",
      `KABUPATEN/KOTA` == "KABUPATEN BANDUNG" ~ "Bandung",
      `KABUPATEN/KOTA` == "KABUPATEN GARUT" ~ "Garut",
      `KABUPATEN/KOTA` == "KABUPATEN TASIKMALAYA" ~ "Tasikmalaya",
      `KABUPATEN/KOTA` == "KABUPATEN CIAMIS" ~ "Ciamis",
      `KABUPATEN/KOTA` == "KABUPATEN KUNINGAN" ~ "Kuningan",
      `KABUPATEN/KOTA` == "KABUPATEN CIREBON" ~ "Cirebon",
      `KABUPATEN/KOTA` == "KABUPATEN MAJALENGKA" ~ "Majalengka",
      `KABUPATEN/KOTA` == "KABUPATEN SUMEDANG" ~ "Sumedang",
      `KABUPATEN/KOTA` == "KABUPATEN INDRAMAYU" ~ "Indramayu",
      `KABUPATEN/KOTA` == "KABUPATEN SUBANG" ~ "Subang",
      `KABUPATEN/KOTA` == "KABUPATEN PURWAKARTA" ~ "Purwakarta",
      `KABUPATEN/KOTA` == "KABUPATEN KARAWANG" ~ "Karawang",
      `KABUPATEN/KOTA` == "KABUPATEN BEKASI" ~ "Bekasi",
      `KABUPATEN/KOTA` == "KABUPATEN BANDUNG BARAT" ~ "Bandung Barat",
      `KABUPATEN/KOTA` == "KABUPATEN PANGANDARAN" ~ "Pangandaran",
      # Kota
      `KABUPATEN/KOTA` == "KOTA BOGOR" ~ "Kota Bogor",
      `KABUPATEN/KOTA` == "KOTA SUKABUMI" ~ "Kota Sukabumi",
      `KABUPATEN/KOTA` == "KOTA BANDUNG" ~ "Kota Bandung",
      `KABUPATEN/KOTA` == "KOTA CIREBON" ~ "Kota Cirebon",
      `KABUPATEN/KOTA` == "KOTA BEKASI" ~ "Kota Bekasi",
      `KABUPATEN/KOTA` == "KOTA DEPOK" ~ "Depok",
      `KABUPATEN/KOTA` == "KOTA CIMAHI" ~ "Kota Cimahi",
      `KABUPATEN/KOTA` == "KOTA TASIKMALAYA" ~ "Kota Tasikmalaya",
      `KABUPATEN/KOTA` == "KOTA BANJAR" ~ "Kota Banjar",
      TRUE ~ `KABUPATEN/KOTA`
    )
  )

# Gabungkan data TBC dengan shapefile
jabar_data <- jabar_shp %>%
  left_join(data_tbc, by = c("NAME_2" = "Nama_Matching"))

# Validasi
missing_data <- jabar_data %>%
  filter(is.na(`Jumlah Penduduk`)) %>%
  st_drop_geometry() %>%
  select(NAME_2)

if(nrow(missing_data) > 0) {
  cat("\n⚠️ WARNING: Wilayah yang tidak memiliki data TBC:\n")
  print(missing_data$NAME_2)
  cat("\nPeriksa kembali nama di data Excel!\n")
} else {
  cat("\n✅ SUKSES: Semua 26 wilayah memiliki data lengkap!\n")
}
## 
## ✅ SUKSES: Semua 26 wilayah memiliki data lengkap!
# Data final untuk analisis
jabar_complete <- jabar_data %>%
  filter(!is.na(`Jumlah Penduduk`))

cat("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
## 
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
cat("📊 RINGKASAN DATA:\n")
## 📊 RINGKASAN DATA:
cat("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
cat("• Total wilayah administratif: 26\n")
## • Total wilayah administratif: 26
cat("• Wilayah dengan data lengkap:", nrow(jabar_complete), "\n")
## • Wilayah dengan data lengkap: 26
cat("• Data siap untuk analisis spasial:", 
    ifelse(nrow(jabar_complete) == 26, "✅ YA", "❌ CEK LAGI"), "\n")
## • Data siap untuk analisis spasial: ✅ YA
cat("\n✅ Data berhasil digabungkan!\n")
## 
## ✅ Data berhasil digabungkan!
library(sf)
library(tidyverse)
library(readxl)
library(tmap)

# 1. LOAD DATA TBC - PAKAI PATH LENGKAP
data_tbc <- read_excel("C:/Users/ASUS/Documents/Dashboard_TBC_Jabar/Data/Data Epidemiologi.xlsx")

cat("✅ Data TBC loaded:", nrow(data_tbc), "baris\n\n")
## ✅ Data TBC loaded: 27 baris
# 2. HITUNG PREVALENSI & BUAT MATCHING NAME
data_tbc <- data_tbc %>%
  mutate(
    # Hitung prevalensi
    Jumlah_Penduduk = as.numeric(`Jumlah Penduduk`),
    Jumlah_Kasus_TBC = as.numeric(`Jumlah Kasus TBC`),
    Prevalensi_per_100k = (Jumlah_Kasus_TBC / Jumlah_Penduduk) * 100000,
    
    # HARMONISASI NAMA
    Nama_Matching = case_when(
      `KABUPATEN/KOTA` == "KABUPATEN BOGOR" ~ "Bogor",
      `KABUPATEN/KOTA` == "KABUPATEN SUKABUMI" ~ "Sukabumi",
      `KABUPATEN/KOTA` == "KABUPATEN CIANJUR" ~ "Cianjur",
      `KABUPATEN/KOTA` == "KABUPATEN BANDUNG" ~ "Bandung",
      `KABUPATEN/KOTA` == "KABUPATEN GARUT" ~ "Garut",
      `KABUPATEN/KOTA` == "KABUPATEN TASIKMALAYA" ~ "Tasikmalaya",
      `KABUPATEN/KOTA` == "KABUPATEN CIAMIS" ~ "Ciamis",
      `KABUPATEN/KOTA` == "KABUPATEN KUNINGAN" ~ "Kuningan",
      `KABUPATEN/KOTA` == "KABUPATEN CIREBON" ~ "Cirebon",
      `KABUPATEN/KOTA` == "KABUPATEN MAJALENGKA" ~ "Majalengka",
      `KABUPATEN/KOTA` == "KABUPATEN SUMEDANG" ~ "Sumedang",
      `KABUPATEN/KOTA` == "KABUPATEN INDRAMAYU" ~ "Indramayu",
      `KABUPATEN/KOTA` == "KABUPATEN SUBANG" ~ "Subang",
      `KABUPATEN/KOTA` == "KABUPATEN PURWAKARTA" ~ "Purwakarta",
      `KABUPATEN/KOTA` == "KABUPATEN KARAWANG" ~ "Karawang",
      `KABUPATEN/KOTA` == "KABUPATEN BEKASI" ~ "Bekasi",
      `KABUPATEN/KOTA` == "KABUPATEN BANDUNG BARAT" ~ "Bandung Barat",
      `KABUPATEN/KOTA` == "KABUPATEN PANGANDARAN" ~ "Pangandaran",
      # Kota
      `KABUPATEN/KOTA` == "KOTA BOGOR" ~ "Kota Bogor",
      `KABUPATEN/KOTA` == "KOTA SUKABUMI" ~ "Kota Sukabumi",
      `KABUPATEN/KOTA` == "KOTA BANDUNG" ~ "Kota Bandung",
      `KABUPATEN/KOTA` == "KOTA CIREBON" ~ "Kota Cirebon",
      `KABUPATEN/KOTA` == "KOTA BEKASI" ~ "Kota Bekasi",
      `KABUPATEN/KOTA` == "KOTA DEPOK" ~ "Depok",
      `KABUPATEN/KOTA` == "KOTA CIMAHI" ~ "Kota Cimahi",
      `KABUPATEN/KOTA` == "KOTA TASIKMALAYA" ~ "Kota Tasikmalaya",
      `KABUPATEN/KOTA` == "KOTA BANJAR" ~ "Kota Banjar",
      TRUE ~ `KABUPATEN/KOTA`
    )
  )

cat("✅ Prevalensi dihitung\n")
## ✅ Prevalensi dihitung
cat("✅ Nama wilayah diharmonisasi\n\n")
## ✅ Nama wilayah diharmonisasi
# 3. LOAD SHAPEFILE
jabar_shp <- st_read("C:/Users/ASUS/Documents/Dashboard_TBC_Jabar/Data/gadm41_IDN_2.shp", 
                     quiet = TRUE) %>%
  filter(NAME_1 == "Jawa Barat") %>%
  filter(NAME_2 != "Waduk Cirata") %>%
  mutate(NAME_2 = case_when(
    NAME_2 == "Banjar" ~ "Kota Banjar",
    NAME_2 == "Cimahi" ~ "Kota Cimahi",
    TRUE ~ NAME_2
  ))

cat("✅ Shapefile loaded:", nrow(jabar_shp), "wilayah\n\n")
## ✅ Shapefile loaded: 26 wilayah
# 4. CEK MATCHING
cat("🔍 CEK MATCHING NAMA:\n")
## 🔍 CEK MATCHING NAMA:
not_in_data <- setdiff(jabar_shp$NAME_2, data_tbc$Nama_Matching)
not_in_shp <- setdiff(data_tbc$Nama_Matching, jabar_shp$NAME_2)

if(length(not_in_data) > 0) {
  cat("❌ Di shapefile tapi TIDAK di data:\n")
  print(not_in_data)
}
if(length(not_in_shp) > 0) {
  cat("❌ Di data tapi TIDAK di shapefile:\n")
  print(not_in_shp)
}
## ❌ Di data tapi TIDAK di shapefile:
## [1] "Pangandaran"
# 5. JOIN DATA
jabar_complete <- jabar_shp %>%
  left_join(data_tbc, by = c("NAME_2" = "Nama_Matching")) %>%
  filter(!is.na(Prevalensi_per_100k))

cat("\n✅ Data siap! Wilayah lengkap:", nrow(jabar_complete), "\n")
## 
## ✅ Data siap! Wilayah lengkap: 26
# 6. BUAT KATEGORI
quartiles <- quantile(jabar_complete$Prevalensi_per_100k, probs = c(0, 0.25, 0.5, 0.75, 1))

jabar_complete <- jabar_complete %>%
  mutate(
    Kategori_Prevalensi = case_when(
      Prevalensi_per_100k < quartiles[2] ~ "Rendah",
      Prevalensi_per_100k < quartiles[3] ~ "Sedang",
      Prevalensi_per_100k < quartiles[4] ~ "Tinggi",
      TRUE ~ "Sangat Tinggi"
    ),
    Kategori_Prevalensi = factor(Kategori_Prevalensi,
                                  levels = c("Rendah", "Sedang", "Tinggi", "Sangat Tinggi"))
  )

# 7. BUAT PETA
peta_kategori <- tm_shape(jabar_complete) +
  tm_fill("Kategori_Prevalensi",
          title = "Kategori Prevalensi\n(per 100k penduduk)",
          palette = c("Rendah" = "#feedde",
                      "Sedang" = "#fdbe85",
                      "Tinggi" = "#fd8d3c",
                      "Sangat Tinggi" = "#d94701")) +
  tm_borders(col = "white", lwd = 1.8) +
  tm_text("NAME_2", size = 0.5, col = "black", fontface = "bold",
          auto.placement = TRUE, remove.overlap = TRUE) +
  tm_layout(
    main.title = "Peta Kategori Prevalensi TBC di Jawa Barat Tahun 2024",
    main.title.size = 1.4,
    main.title.fontface = "bold",
    legend.outside = TRUE,
    legend.outside.position = "right",
    frame = TRUE
  ) +
  tm_compass(type = "8star", position = c("left", "top"), size = 2.5) +
  tm_scale_bar(position = c("left", "bottom")) +
  tm_credits("Sumber: Dinkes Jabar, 2024", position = c("right", "bottom"))

print(peta_kategori)

cat("\n✅ PETA BERHASIL DIBUAT!\n")
## 
## ✅ PETA BERHASIL DIBUAT!

Gambar 4.4 Peta kategori prevalensi TBC menunjukkan distribusi spasial kasus di Jawa Barat. Kategorisasi berdasarkan quartile distribusi data untuk mengidentifikasi wilayah prioritas intervensi.

library(spdep)
## Warning: package 'spdep' was built under R version 4.3.3
## Loading required package: spData
## Warning: package 'spData' was built under R version 4.3.3
## To access larger datasets in this package, install the spDataLarge
## package with: `install.packages('spDataLarge',
## repos='https://nowosad.github.io/drat/', type='source')`
# 1. Buat Spatial Weights Matrix
neighbors <- poly2nb(jabar_complete, queen = TRUE)
weights <- nb2listw(neighbors, style = "W", zero.policy = TRUE)

# 2. Hitung Moran's I (ukuran autokorelasi spasial)
moran_test <- moran.test(jabar_complete$Prevalensi_per_100k, weights)

cat(" UJI MORAN'S I (Autokorelasi Spasial)\n")
##  UJI MORAN'S I (Autokorelasi Spasial)
cat("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
## ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
cat("Moran's I        :", round(moran_test$estimate[1], 4), "\n")
## Moran's I        : 0.0064
cat("Expected Value   :", round(moran_test$estimate[2], 4), "\n")
## Expected Value   : -0.04
cat("P-value          :", round(moran_test$p.value, 4), "\n")
## P-value          : 0.369
cat("\nInterpretasi:\n")
## 
## Interpretasi:
if(moran_test$p.value < 0.05 && moran_test$estimate[1] > 0) {
  cat("Terdapat autokorelasi spasial POSITIF yang signifikan\n")
  cat("   → Wilayah dengan prevalensi tinggi cenderung bertetangga\n")
  cat("   → Ada pengelompokan spasial (clustering)\n")
} else if(moran_test$p.value < 0.05 && moran_test$estimate[1] < 0) {
  cat("Terdapat autokorelasi spasial NEGATIF yang signifikan\n")
  cat("   → Wilayah tinggi bersebelahan dengan wilayah rendah\n")
} else {
  cat("TIDAK ada autokorelasi spasial yang signifikan\n")
  cat("   → Distribusi acak secara spasial\n")
}
## TIDAK ada autokorelasi spasial yang signifikan
##    → Distribusi acak secara spasial
# 3. LISA (Local Indicators of Spatial Association)
local_moran <- localmoran(jabar_complete$Prevalensi_per_100k, weights)
jabar_complete$moran_cluster <- as.factor(
  ifelse(local_moran[,5] > 0.05, "Not Significant",
         ifelse(local_moran[,1] > 0 & local_moran[,4] > 0, "High-High",
                ifelse(local_moran[,1] < 0 & local_moran[,4] > 0, "Low-High",
                       ifelse(local_moran[,1] > 0 & local_moran[,4] < 0, "High-Low", "Low-Low"))))
)

cat("\n LISA Cluster:\n")
## 
##  LISA Cluster:
table(jabar_complete$moran_cluster)
## 
##       High-High Not Significant 
##               2              24

Uji Moran’s I (Autokorelasi Spasial Global) Nilai Moran’s I sebesar 0,0064 dengan expected value –0,04 dan p-value 0,369 (>0,05) menunjukkan bahwa tidak terdapat autokorelasi spasial yang signifikan pada distribusi prevalensi TBC di Provinsi Jawa Barat. Dengan demikian, penyebaran TBC cenderung acak secara spasial, di mana wilayah dengan prevalensi tinggi tidak selalu berdekatan dengan wilayah yang juga tinggi, begitu pula sebaliknya.

Analisis LISA Berdasarkan analisis LISA, terdapat dua wilayah dengan pola High–High yang mengindikasikan potensi klaster lokal prevalensi tinggi, sedangkan 24 wilayah lainnya tidak signifikan secara spasial. Kondisi ini menunjukkan bahwa hanya terdapat sedikit daerah dengan kecenderungan klaster TBC lokal, dan secara umum distribusi kasus TBC di Jawa Barat tidak membentuk pola spasial yang konsisten.

Interpretasi keseluruhan: Hasil ini menandakan bahwa persebaran TBC di Jawa Barat lebih dipengaruhi oleh karakteristik internal wilayah seperti kepadatan penduduk, kondisi perumahan, dan faktor sosial-ekonomi dibandingkan efek kedekatan geografis antarwilayah. Dengan demikian, strategi pengendalian TBC sebaiknya difokuskan pada pendekatan berbasis faktor risiko lokal daripada intervensi spasial antarwilayah.

4.6 Analisis Korelasi Faktor Risiko TBC

Setelah memahami pola distribusi geografis kasus TBC melalui analisis spasial, langkah selanjutnya adalah menganalisis hubungan antara faktor risiko sosial-ekonomi dengan prevalensi TBC. Analisis korelasi dilakukan untuk menguji hipotesis bahwa kepadatan penduduk, tingkat kemiskinan, dan kondisi perumahan memiliki hubungan dengan tingkat prevalensi TBC di suatu wilayah.

library(corrplot)
library(dplyr)
library(readxl)

# PAKAI PATH LENGKAP, JANGAN PAKAI here()
data_tbc <- read_excel("C:/Users/ASUS/Documents/Dashboard_TBC_Jabar/Data/Data Epidemiologi.xlsx")
# Bersihkan data
data_tbc_clean <- data_tbc %>%
  mutate(
    Prevalensi_TBC = as.numeric(`Jumlah Kasus TBC`) / as.numeric(`Jumlah Penduduk`) * 100000,
    Rumah_Layak = as.numeric(`Rumah Layak Huni%`),
    Kemiskinan = as.numeric(`Persentase Penduduk Miskin%`),
    Kepadatan = as.numeric(`Kepadatan Penduduk (Jiwa/KM2)`)
  )

# Pilih variabel untuk korelasi
data_numeric <- data_tbc_clean %>%
  select(Prevalensi_TBC, Rumah_Layak, Kemiskinan, Kepadatan) %>%
  na.omit()

# Rename kolom untuk label yang rapi
colnames(data_numeric) <- c("Prevalensi\nTBC", 
                             "Rumah Layak\n(%)", 
                             "Kemiskinan\n(%)", 
                             "Kepadatan\nPenduduk")

# Hitung matriks korelasi
cor_matrix <- cor(data_numeric, use = "complete.obs")

# Visualisasi corrplot LEBIH BAGUS
corrplot(cor_matrix, 
         method = "color",            # Pakai color lebih jelas
         type = "upper",              # Upper triangle lebih rapi
         addCoef.col = "black",       # Tambah angka korelasi
         number.cex = 1.3,            # Ukuran angka lebih besar
         number.font = 2,             # Bold untuk angka
         tl.col = "black",            # Warna label
         tl.srt = 45,                 # Rotasi label 45 derajat
         tl.cex = 1.1,                # Ukuran teks label
         col = colorRampPalette(c("#EF4444", "white", "#3B82F6"))(200),  # Merah-Putih-Biru
         cl.cex = 0.9,                # Ukuran legend
         diag = TRUE,                 # Tampilkan diagonal
         title = "Matriks Korelasi Variabel TBC",
         mar = c(0, 0, 2, 0),
         addgrid.col = "gray80")      # Tambah grid

# Print hasil korelasi
print(round(cor_matrix, 3))
##                     Prevalensi\nTBC Rumah Layak\n(%) Kemiskinan\n(%)
## Prevalensi\nTBC               1.000           -0.076          -0.325
## Rumah Layak\n(%)             -0.076            1.000           0.212
## Kemiskinan\n(%)              -0.325            0.212           1.000
## Kepadatan\nPenduduk          -0.448           -0.059           0.361
##                     Kepadatan\nPenduduk
## Prevalensi\nTBC                  -0.448
## Rumah Layak\n(%)                 -0.059
## Kemiskinan\n(%)                   0.361
## Kepadatan\nPenduduk               1.000
# Tabel ringkasan korelasi dengan Prevalensi TBC
cor_summary <- data.frame(
  Variabel = c("Rumah Layak (%)", "Kemiskinan (%)", "Kepadatan Penduduk"),
  Korelasi = c(
    cor(data_numeric[,1], data_numeric[,2]),
    cor(data_numeric[,1], data_numeric[,3]),
    cor(data_numeric[,1], data_numeric[,4])
  )
) %>%
  mutate(
    Korelasi = round(Korelasi, 3),
    Kekuatan = case_when(
      abs(Korelasi) < 0.3 ~ "Sangat Lemah",
      abs(Korelasi) < 0.5 ~ "Lemah",
      abs(Korelasi) < 0.7 ~ "Sedang",
      abs(Korelasi) < 0.9 ~ "Kuat",
      TRUE ~ "Sangat Kuat"
    ),
    Arah = ifelse(Korelasi > 0, "Positif", "Negatif")
  )

print(cor_summary)
##             Variabel Korelasi     Kekuatan    Arah
## 1    Rumah Layak (%)   -0.076 Sangat Lemah Negatif
## 2     Kemiskinan (%)   -0.325        Lemah Negatif
## 3 Kepadatan Penduduk   -0.448        Lemah Negatif
# Simpan gambar dengan kualitas tinggi
png("matriks_korelasi.png", width = 1000, height = 1000, res = 150)
corrplot(cor_matrix, 
         method = "color",
         type = "upper",
         addCoef.col = "black",
         number.cex = 1.3,
         number.font = 2,
         tl.col = "black",
         tl.srt = 45,
         tl.cex = 1.1,
         col = colorRampPalette(c("#EF4444", "white", "#3B82F6"))(200),
         cl.cex = 0.9,
         diag = TRUE,
         title = "Matriks Korelasi Variabel TBC",
         mar = c(0, 0, 2, 0),
         addgrid.col = "gray80")
dev.off()
## png 
##   2

interpretasi : Berdasarkan hasil korelasi, kepadatan penduduk dan kemiskinan menunjukkan hubungan negatif sedang dengan prevalensi TBC, menandakan bahwa wilayah padat dan miskin memiliki risiko penularan yang lebih tinggi. Sebaliknya, proporsi rumah layak huni tidak menunjukkan hubungan kuat terhadap variasi TBC. Pola ini menegaskan bahwa determinan sosial dan lingkungan makro memiliki peranan penting dalam penyebaran TBC di Jawa Barat.

Temuan ini menjadi dasar untuk memahami variasi spasial TBC di Jawa Barat yang tidak semata-mata ditentukan oleh kedekatan geografis, tetapi oleh karakteristik sosial-ekonomi masing-masing wilayah.

BAB V.KESIMPULAN DAN SARAN

BAB V. KESIMPULAN DAN SARAN

5.1 Kesimpulan

Berdasarkan analisis epidemiologis kasus tuberkulosis (TBC) di Provinsi Jawa Barat tahun 2024 dapat disimpulkan:

  1. Beban Penyakit. Tercatat 229.683 kasus TBC dengan prevalensi rata-rata 505,03 per 100.000 penduduk. Terdapat disparitas antarwilayah (prevalensi berkisar antara 222,99–1.195,30 per 100.000).
  2. Faktor Risiko. Korelasi menunjukkan hubungan negatif sedang antara kepadatan penduduk (r = -0,45) dan kemiskinan (r = -0,32) dengan prevalensi TBC; rumah layak huni menunjukkan korelasi sangat lemah (r = -0,08). Hal ini mengindikasikan determinan multifaktorial dengan peran kuat faktor sosial-ekonomi lokal.
  3. Pola Spasial. Moran’s I = 0,0064 (p = 0,369) menandakan tidak terdapat autokorelasi spasial signifikan; penyebaran prevalensi cenderung acak secara geografis.
  4. Triad Epidemiologi. Agen (Mycobacterium tuberculosis) tersebar merata; faktor host (imunitas, komorbiditas) kemungkinan lebih berpengaruh pada variasi lokal; faktor lingkungan bersifat spesifik per wilayah.

Ringkasnya, TBC tetap menjadi masalah utama di Jawa Barat dengan beban lebih tinggi di beberapa wilayah perkotaan; pengendalian perlu mempertimbangkan konteks sosial, ekonomi, dan lingkungan setempat.

5.2 Saran

  • Kebijakan Pengendalian. Prioritaskan intervensi pada wilayah berprevalensi tinggi (mis. Kota Cirebon, Bogor, Sukabumi) melalui peningkatan active case finding, penguatan layanan DOTS, dan alokasi sumber daya terfokus.
  • Pendekatan Berbasis Wilayah. Karena pola spasial tidak signifikan secara global, setiap kabupaten/kota perlu merancang strategi yang sesuai kondisi lokal (perbaikan ventilasi rumah, program pengurangan kemiskinan, edukasi kesehatan).
  • Penelitian Lanjutan. Disarankan studi longitudinal dan analisis berbasis data individu (case-control atau kohort) untuk mengidentifikasi faktor host dan menilai dinamika temporal.

5.3 Keterbatasan

Penelitian ini menggunakan desain ekologi dengan data agregat satu tahun sehingga tidak dapat menguji kausalitas pada tingkat individu dan tidak memantau tren waktu. Variabel klinis (mis. HIV, DM), perilaku, dan potensi underreporting tidak sepenuhnya tercakup.

5.4 Penutup

Pengendalian TBC di Jawa Barat membutuhkan pendekatan multisektor, berbasis bukti, dan sensitif terhadap kondisi lokal. Kolaborasi lintas pemangku kepentingan penting untuk mencapai target eliminasi TBC 2030.

Lampiran

Lampiran 1. Syntax Pembuatan Diagram Kerangka Konseptual Penelitian

Berikut adalah kode R yang digunakan untuk menghasilkan Gambar 2.1 menggunakan paket DiagrammeR.

library(DiagrammeR)

grViz("
digraph kerangka {
  graph [layout = dot, rankdir = TB]
  node [shape = rectangle, style = filled, fontname = Arial, fontsize = 10]
  edge [color = '#555555', penwidth = 1.2]
  
  A [label='Agent\\n(Mycobacterium tuberculosis)', fillcolor='#FEE2E2']
  H [label='Host\\n(Imunitas, HIV, DM, Gizi)', fillcolor='#FEF3C7']
  E [label='Environment\\n(Sosial ekonomi, perumahan, kepadatan)', fillcolor='#DCFCE7']
  D [label='Determinant Wilayah\\nKepadatan, Kemiskinan, Rumah Layak', fillcolor='#DBEAFE']
  P [label='Prevalensi TBC\\n(per 100.000 penduduk)', fillcolor='#FECACA']
  S [label='Analisis Spasial\\n(Moran’s I, LISA)', fillcolor='#E0E7FF']
  R [label='Rekomendasi Kebijakan\\nBerbasis Wilayah', fillcolor='#D1FAE5']
  
  A -> H
  H -> E
  E -> D
  D -> P
  P -> S
  S -> R
}
")

Lampiran A: Kode Lengkap Aplikasi Shiny

library(shiny)
library(bs4Dash)
library(dplyr)
library(leaflet)
library(sf)
library(DT)
library(ggplot2)
library(plotly)
library(corrplot)
library(RColorBrewer)
library(readxl)
library(stringr)
library(shinydashboard)
library(sf)
library(dplyr)
library(spdep)
library(spatialreg)
library(car)
library(DT)
library(shinycssloaders)
library(plotly)
library(viridis)

# ==== SETUP WORKING DIRECTORY & BACA DATA ====
setwd("C:/Users/Lenovo/Downloads/ShinyProject")
list.files("C:/Users/Lenovo/Downloads/ShinyProject")

5# Baca data CSV
data <- read.csv("dataTBC.csv")
colnames(data) <- c("Kabupaten Kota", "Jumlah Penduduk", "Rumah Layak Huni", 
                    "Persentase Penduduk Miskin", "Kepadatan Penduduk (Jiwa/KM2)", 
                    "Jumlah Kasus TBC")

# Proses data untuk analisis
data_processed <- data %>%
  mutate(
    Wilayah = `Kabupaten Kota`,
    Populasi = `Jumlah Penduduk`,
    Rumah_Layak_Pct = `Rumah Layak Huni`,
    Miskin_Pct = `Persentase Penduduk Miskin`,
    Kepadatan = `Kepadatan Penduduk (Jiwa/KM2)`,
    Kasus_TBC = `Jumlah Kasus TBC`,
    Wilayah_Raw = Wilayah,
    Wilayah_Clean = toupper(trimws(gsub("KABUPATEN |KOTA ", "", Wilayah))),
    Prevalensi = ifelse(!is.na(Kasus_TBC) & !is.na(Populasi) & Populasi > 0,
                        (Kasus_TBC / Populasi) * 100000, NA),
    Attack_Rate = ifelse(!is.na(Kasus_TBC) & !is.na(Populasi) & Populasi > 0,
                         (Kasus_TBC / Populasi) * 100, NA),
    Incidence_Rate = Prevalensi,
    CFR = NA,
    Tipe = ifelse(grepl("^KOTA", toupper(Wilayah_Raw)), "Kota", "Kabupaten")
  )

# ==== BACA SHAPEFILE ====
batas_all <- st_read("gadm41_IDN_2.shp")

batas_jabar <- batas_all %>%
  filter(NAME_1 %in% c("West Java", "Jawa Barat", "JAWA BARAT", "WEST JAVA")) %>%
  select(NAME_2, geometry) %>%
  mutate(
    NAME_2 = toupper(NAME_2),                                # huruf besar semua
    NAME_2 = str_replace_all(NAME_2, "KABUPATEN ", ""),      # hapus "KABUPATEN "
    NAME_2 = str_replace_all(NAME_2, "KOTA ", ""),            # hapus "KOTA "
    NAME_2 = str_replace_all(NAME_2, "WADUK CIRATA", "PANGANDARAN"),  # ubah nama khusus
    NAME_2 = str_trim(NAME_2)
  )

batas_jabar <- batas_jabar %>%
  group_by(NAME_2) %>%
  summarise(geometry = sf::st_union(geometry)) %>%  # gabungkan poligon duplikat
  ungroup()

if (nrow(batas_jabar) == 0) {
  stop("ERROR: Tidak ada data Jawa Barat di shapefile!")
}

ui <- bs4DashPage(
  title = "Analisis Epidemiologi pada Kasus TBC di Jawa Barat 2024",
  
  # ===== HEADER =====
  header = bs4DashNavbar(
    skin = "light",
    status = "white",
    border = FALSE,
    sidebarIcon = icon("bars"),
    controlbarIcon = icon("gear"),
    rightUi = NULL,
    tags$head(
      tags$style(HTML("
        .main-header.navbar {
          background-color: #ed8eb8 !important;
          color: white !important;
        }
      "))
    )
  ),
  
  # ===== SIDEBAR =====
  sidebar = bs4DashSidebar(
    skin = "light",
    status = "pink",
    title = "DBD Dashboard",
    brandColor = "pink",
    opacity = 0.9,
    bs4SidebarMenu(
      bs4SidebarMenuItem("Home", tabName = "home", icon = icon("home")),
      bs4SidebarMenuItem("Data", tabName = "data", icon = icon("database")),
      bs4SidebarMenuItem("Statistika Deskriptif", tabName = "statistik", icon = icon("table")),
      bs4SidebarMenuItem("Ukuran Epidemiologi", tabName = "epidemiologi", icon = icon("calculator")),
      bs4SidebarMenuItem("Analisis & Visualisasi", tabName = "analisis", icon = icon("chart-line")),
      bs4SidebarMenuItem("Peta Distribusi", tabName = "peta", icon = icon("map")),
      bs4SidebarMenuItem("Interpretasi & Rekomendasi", tabName = "interpretasi", icon = icon("lightbulb"))
    )
  ),
  
  # ===== BODY (BENAR) =====
  body = bs4DashBody(
    
    # CSS khusus card
    tags$head(
      tags$style(HTML("
        .card-profil .card-header,
        .card-overview .card-header,
        .card-ringkas .card-header,
        .card-visual .card-header,
        .card-kontrol .card-header,
        .card-visdat .card-header,
        .card-peta .card-header {
          background-color: #932f60 !important;
          color: white !important;
          font-weight: bold;
        }
         h1, h2, h3, h4, h5, h6 {
      color: #932f60 !important;
      font-weight: bold !important;
      
        .content-header h3 {
      color: #932f60 !important;
      font-weight: bold !important;
         }
      "))
    ),
    
    bs4TabItems(
      # ---- TAB HOME ----
      bs4TabItem(
        tabName = "home",
        fluidRow(
          # CARD PROFIL PENELITI
          bs4Card(
            title = "Profil Peneliti",
            width = 6,
            solidHeader = TRUE,
            collapsible = TRUE,
            class = "card-profil",
            
            fluidRow(
              column(8,
                     tags$h4("Nama: Reira Falisha Adrevi"),
                     tags$h5("NPM: 140610230002"),
                     tags$p("Mahasiswa Statistika, Universitas Padjadjaran")
              )
            ),
            tags$hr(),
            fluidRow(
              column(8,
                     tags$h4("Nama: Shahnaz Putri Dendawijaya"),
                     tags$h5("NPM: 140610230017"),
                     tags$p("Mahasiswa Statistika, Universitas Padjadjaran")
              )
            ),
            tags$hr(),
            fluidRow(
              column(8,
                     tags$h4("Nama: Mona Yola Lumban Raja"),
                     tags$h5("NPM: 140610230081"),
                     tags$p("Mahasiswa Statistika, Universitas Padjadjaran")
              )
            )
          ),
          
          # CARD OVERVIEW DATA
          bs4Card(
            title = "Overview Dashboard",
            width = 6,
            solidHeader = TRUE,
            collapsible = TRUE,
            class = "card-overview",
            tags$p("Hal yang dapat ditemukan dalam dashboard :"),
            tags$ul(
              tags$li("Hasil perhitungan kejadian TBC dari sisi epidemiologis"),
              tags$li("Visualisasi data penelitian terhadap kasus TBC")
            ),
            tags$p("Data yang digunakan dalam analisis ini meliputi:"),
            tags$ul(
              tags$li("Jumlah kasus TBC di Jawa Barat tahun 2024"),
              tags$li("Jumlah penduduk"),
              tags$li("Persentase Penduduk Miskin"),
              tags$li("Kepadatan Penduduk"),
              tags$li("Jumlah rumah layak Huni")
            )
          )
        )
      ),
      
      # ---- TAB DATA ----
      bs4TabItem(
        tabName = "data",
        
        # Judul Halaman
        h3("Data Kasus TBC dan Faktor Pendukung di Provinsi Jawa Barat Tahun 2024"),
        br(),
        bs4Card(
          width = 12,
          solidHeader = TRUE,
          DT::dataTableOutput("tabel_data")
        )
      ),
        
      
      # ==================== TAB STATISTIK (DARI SYNTAX 2) ====================
      bs4TabItem(
        tabName = "statistik",
        h2("Statistika Deskriptif"),
        
        bs4Card(
          title = "Ringkasan Statistik Variabel Dasar",
          width = 12,
          solidHeader = TRUE,
          collapsible = TRUE,
          class = "card-ringkas",
          DTOutput("summary_stats")
        ),
        
        bs4Card(
          width = 12,
          solidHeader = TRUE,
          class = "card-visual",
          title = "Visualisasi Variabel",
          fluidRow(
            column(6,
                   selectInput("desc_variable", "Pilih Variabel:",
                               choices = c("Pilih..." = "",
                                           "Jumlah Kasus TBC" = "Kasus_TBC",
                                           "Populasi" = "Populasi",
                                           "Persentase Kemiskinan" = "Miskin_Pct",
                                           "Kepadatan Penduduk" = "Kepadatan",
                                           "Rumah Layak Huni" = "Rumah_Layak_Pct"))
            ),
            column(6,
                   selectInput("desc_plot_type", "Pilih Jenis Plot:",
                               choices = c("Histogram" = "histogram",
                                           "Boxplot" = "boxplot"))
            )
          ),
          conditionalPanel(
            condition = "input.desc_variable != ''",
            plotlyOutput("desc_plot", height = "450px")
          ),
          conditionalPanel(
            condition = "input.desc_variable == ''",
            h4(style = "text-align: center; color: #888; padding: 60px;",
               icon("chart-bar"), br(), br(),
               "Pilih variabel untuk melihat visualisasi")
          )
        )
      ),
      
      # ==================== TAB EPIDEMIOLOGI (DARI SYNTAX 2) ====================
      bs4TabItem(
        tabName = "epidemiologi",
        h2("Ukuran Epidemiologi TBC Jawa Barat 2024"),
        
        bs4Card(
          width = 12,
          solidHeader = TRUE,
          title = "Ringkasan Statistik Epidemiologi",
          DTOutput("epi_summary")
        ),
        
        bs4Card(
          width = 12,
          solidHeader = TRUE,
          title = "Detail Lengkap per Wilayah (27 Kabupaten/Kota)",
          DTOutput("epi_detail")
        )
      ),
      
      # ==================== TAB ANALISIS (DARI SYNTAX 2) ====================
      bs4TabItem(
        tabName = "analisis",
        h2("Analisis & Visualisasi"),
        
        bs4Card(
          width = 12,
          status = "info",
          solidHeader = TRUE,
          title = "Kontrol Visualisasi",
          class = "card-kontrol",
          fluidRow(
            column(4,
                   selectInput("plot_type", "Pilih Jenis Grafik:",
                               choices = c("Pilih..." = "",
                                           "Bar Chart Prevalensi" = "bar_prev",
                                           "Scatter: Layak Huni vs Prevalensi" = "scatter_layakhuni",
                                           "Scatter: Kepadatan vs Prevalensi" = "scatter_kepadatan",
                                           "Scatter: Kemiskinan vs Prevalensi" = "scatter_kemiskinan",
                                           "Distribusi Jumlah Kasus" = "dist_kasus",
                                           "Distribusi Kemiskinan" = "dist_kemiskinan",
                                           "Distribusi Kepadatan" = "dist_kepadatan",
                                           "Distribusi Rumah Layak" = "dist_rumah",
                                           "Perbandingan Kota vs Kabupaten" = "compare_type"))
            ),
            column(4,
                   selectInput("sort_order", "Urutkan:",
                               choices = c("Tertinggi ke Terendah" = "desc",
                                           "Terendah ke Tertinggi" = "asc"))
            ),
            column(4,
                   sliderInput("top_n", "Tampilkan N Wilayah Teratas:",
                               min = 5, max = 27, value = 27, step = 1)
            )
          )
        ),
        
        bs4Card(
          width = 12,
          status = "success",
          solidHeader = TRUE,
          title = "Visualisasi Data",
          class ="card.visdat",
          conditionalPanel(
            condition = "input.plot_type != ''",
            plotlyOutput("dynamic_plot", height = "500px")
          ),
          conditionalPanel(
            condition = "input.plot_type == ''",
            h4(style = "text-align: center; color: #888; padding: 80px;",
               icon("mouse-pointer"), br(), br(),
               "Pilih jenis grafik untuk melihat visualisasi")
          )
        ),
        
        bs4Card(
          width = 12,
          status = "primary",
          solidHeader = TRUE,
          title = "Top 10 Wilayah Prevalensi Tertinggi",
          plotlyOutput("plot_top10", height = "500px")
        ),
        
        bs4Card(
          width = 12,
          status = "warning",
          solidHeader = TRUE,
          title = "Matriks Korelasi Antar Variabel",
          plotOutput("corr_plot", height = "500px")
        )
      ),
      
      # ==================== TAB PETA (DARI SYNTAX 2) ====================
      bs4TabItem(
        tabName = "peta",
        h2("Peta Distribusi TBC Jawa Barat"),
        
        bs4Card(
          width = 12,
          status = "info",
          solidHeader = TRUE,
          title = "Kontrol Peta",
          class = "card-peta",
          fluidRow(
            column(6,
                   selectInput("map_variable", "Pilih Variabel yang Ditampilkan:",
                               choices = c("Pilih..." = "",
                                           "Prevalensi TBC" = "Prevalensi",
                                           "Jumlah Kasus" = "Kasus_TBC",
                                           "Persentase Kemiskinan" = "Miskin_Pct",
                                           "Kepadatan Penduduk" = "Kepadatan"))
            ),
            column(6,
                   selectInput("map_color", "Pilih Skema Warna:",
                               choices = c("Biru" = "Blues",
                                           "Merah" = "Reds",
                                           "Hijau" = "Greens",
                                           "Ungu" = "Purples"))
            )
          )
        ),
        
        bs4Card(
          width = 12,
          status = "primary",
          solidHeader = TRUE,
          conditionalPanel(
            condition = "input.map_variable != ''",
            leafletOutput("map_tbc", height = 600)
          ),
          conditionalPanel(
            condition = "input.map_variable == ''",
            h4(style = "text-align: center; color: #888; padding: 100px;",
               icon("map-marked-alt"), br(), br(),
               "Pilih variabel yang ingin ditampilkan di peta")
          )
        )
      ),
      
      # ==================== TAB INTERPRETASI (DARI SYNTAX 2) ====================
      bs4TabItem(
        tabName = "interpretasi",
        h2("Interpretasi & Rekomendasi"),
        uiOutput("kesimpulan")
      )
    )
  ),
  
  # ===== CONTROLBAR =====
  controlbar = bs4DashControlbar(
    pinned = TRUE,
    collapsed = TRUE,
    skin = "light",
    tags$h5("Info Tambahan"),
    tags$p("Dashboard ini dibuat guna menyelesaikan Ujian Tengah Semester Epidemiologi")
  ),
  
  # ===== FOOTER =====
  footer = bs4DashFooter(
    fixed = TRUE,
    left = "© 2025 Kelompok 5",
    right = "TBC Analysis Dashboard"
  )
)

server <- function(input, output, session) {
  
  # ==== SUMMARY STATISTICS ====
  output$summary_stats <- DT::renderDataTable({
    data_used <- if (exists("data_processed")) data_processed else data
    
    summary_data <- data.frame(
      Variabel = c("Jumlah Kasus TBC", "Populasi",
                   "Kemiskinan (%)", "Kepadatan (jiwa/km²)", "Rumah Layak (%)"),
      Mean = c(mean(data_used$`Jumlah Kasus TBC`, na.rm = TRUE),
               mean(data_used$`Jumlah Penduduk`, na.rm = TRUE),
               mean(data_used$`Persentase Penduduk Miskin`, na.rm = TRUE),
               mean(data_used$`Kepadatan Penduduk (Jiwa/KM2)`, na.rm = TRUE),
               mean(data_used$`Rumah Layak Huni`, na.rm = TRUE)),
      Median = c(median(data_used$`Jumlah Kasus TBC`, na.rm = TRUE),
                 median(data_used$`Jumlah Penduduk`, na.rm = TRUE),
                 median(data_used$`Persentase Penduduk Miskin`, na.rm = TRUE),
                 median(data_used$`Kepadatan Penduduk (Jiwa/KM2)`, na.rm = TRUE),
                 median(data_used$`Rumah Layak Huni`, na.rm = TRUE)),
      SD = c(sd(data_used$`Jumlah Kasus TBC`, na.rm = TRUE),
             sd(data_used$`Jumlah Penduduk`, na.rm = TRUE),
             sd(data_used$`Persentase Penduduk Miskin`, na.rm = TRUE),
             sd(data_used$`Kepadatan Penduduk (Jiwa/KM2)`, na.rm = TRUE),
             sd(data_used$`Rumah Layak Huni`, na.rm = TRUE)),
      Min = c(min(data_used$`Jumlah Kasus TBC`, na.rm = TRUE),
              min(data_used$`Jumlah Penduduk`, na.rm = TRUE),
              min(data_used$`Persentase Penduduk Miskin`, na.rm = TRUE),
              min(data_used$`Kepadatan Penduduk (Jiwa/KM2)`, na.rm = TRUE),
              min(data_used$`Rumah Layak Huni`, na.rm = TRUE)),
      Max = c(max(data_used$`Jumlah Kasus TBC`, na.rm = TRUE),
              max(data_used$`Jumlah Penduduk`, na.rm = TRUE),
              max(data_used$`Persentase Penduduk Miskin`, na.rm = TRUE),
              max(data_used$`Kepadatan Penduduk (Jiwa/KM2)`, na.rm = TRUE),
              max(data_used$`Rumah Layak Huni`, na.rm = TRUE))
    )
    
    DT::datatable(summary_data,
                  options = list(dom = 't', pageLength = 10),
                  rownames = FALSE) %>%
      DT::formatRound(c("Mean", "Median", "SD", "Min", "Max"), 2)
  })
  
    # ==== TABEL DATA ====
  data <- read.csv("dataTBC.csv", header = TRUE)
  #Output tabel
  output$tabel_data <- DT::renderDataTable({
    DT::datatable(
      data,
      options = list(
        pageLength = 10,
        autoWidth = TRUE,
        scrollX = TRUE
      )
    )
  })
  
  # ==================== PLOT STATISTIKA DESKRIPTIF ====================
  output$desc_plot <- renderPlotly({
    req(input$desc_variable, input$desc_plot_type)
    
    df <- data_processed %>% filter(!is.na(.data[[input$desc_variable]]))
    validate(need(nrow(df) > 0, "Data tidak tersedia untuk variabel ini."))
    
    var_labels <- c(
      "Kasus_TBC" = "Jumlah Kasus TBC",
      "Populasi" = "Populasi",
      "Miskin_Pct" = "Persentase Kemiskinan (%)",
      "Kepadatan" = "Kepadatan Penduduk (jiwa/km²)",
      "Rumah_Layak_Pct" = "Rumah Layak Huni (%)"
    )
    
    var_colors <- c(
      "Kasus_TBC" = "#E74C3C",
      "Populasi" = "#3498DB",
      "Miskin_Pct" = "#F39C12",
      "Kepadatan" = "#9B59B6",
      "Rumah_Layak_Pct" = "#27AE60"
    )
    
    var_name <- var_labels[[input$desc_variable]]
    var_color <- var_colors[[input$desc_variable]]
    
    if (input$desc_plot_type == "histogram") {
      p <- ggplot(df, aes(x = .data[[input$desc_variable]])) +
        geom_histogram(aes(y = ..density..), bins = 15,
                       fill = var_color, alpha = 0.7, color = "white") +
        geom_density(color = "#932f60", size = 1.2) +
        labs(
          x = var_name, y = "Kerapatan (Density)",
          title = paste("Distribusi", var_name)
        ) +
        theme_minimal(base_size = 13)
    } else {
      p <- ggplot(df, aes(y = .data[[input$desc_variable]], x = "")) +
        geom_boxplot(fill = var_color, alpha = 0.7, color = "#932f60", width = 0.4) +
        geom_jitter(width = 0.1, alpha = 0.4, size = 2, color = "#932f60") +
        labs(
          y = var_name, x = "",
          title = paste("Boxplot", var_name)
        ) +
        theme_minimal(base_size = 13) +
        theme(axis.text.x = element_blank())
    }
    
    ggplotly(p) %>%
      layout(hoverlabel = list(bgcolor = "white"))
  })

  
  # ==================== EPIDEMIOLOGI RINGKASAN ====================
  output$epi_summary <- renderDT({
    summary_data <- data.frame(
      Indikator = c(
        "Total Populasi Jawa Barat",
        "Total Kasus TBC",
        "Crude Prevalence Rate (per 100.000)",
        "Attack Rate Rata-rata (%)",
        "Wilayah Prevalensi Tertinggi",
        "Nilai Prevalensi Tertinggi (per 100.000)",
        "Wilayah Prevalensi Terendah",
        "Nilai Prevalensi Terendah (per 100.000)",
        "Standar Deviasi Prevalensi",
        "Koefisien Variasi (%)"
      ),
      Nilai = c(
        format(sum(data_processed$Populasi, na.rm = TRUE), big.mark = "."),
        format(sum(data_processed$Kasus_TBC, na.rm = TRUE), big.mark = "."),
        round((sum(data_processed$Kasus_TBC, na.rm = TRUE) / sum(data_processed$Populasi, na.rm = TRUE)) * 100000, 2),
        round(mean(data_processed$Attack_Rate, na.rm = TRUE), 2),
        data_processed$Wilayah_Clean[which.max(data_processed$Prevalensi)],
        round(max(data_processed$Prevalensi, na.rm = TRUE), 2),
        data_processed$Wilayah_Clean[which.min(data_processed$Prevalensi)],
        round(min(data_processed$Prevalensi, na.rm = TRUE), 2),
        round(sd(data_processed$Prevalensi, na.rm = TRUE), 2),
        round((sd(data_processed$Prevalensi, na.rm = TRUE) / mean(data_processed$Prevalensi, na.rm = TRUE)) * 100, 2)
      ),
      stringsAsFactors = FALSE
    )
    
    datatable(
      summary_data,
      options = list(
        dom = 't',
        pageLength = 15,
        columnDefs = list(list(width = '60%', targets = 0))
      ),
      rownames = FALSE
    ) %>%
      formatStyle(
        'Indikator',
        fontWeight = 'bold',
        color = '#932f60'
      ) %>%
      formatStyle(
        'Nilai',
        backgroundColor = '#F8F9FA'
      )
  })
  
  # ==================== EPIDEMIOLOGI DETAIL ====================
  output$epi_detail <- renderDT({
    df <- data_processed %>% arrange(desc(Prevalensi))
    
    detail_table <- df %>%
      select(Wilayah_Raw, Tipe, Populasi, Kasus_TBC, Prevalensi, Attack_Rate,
             Rumah_Layak_Pct, Miskin_Pct, Kepadatan) %>%
      mutate(
        Populasi = format(Populasi, big.mark = "."),
        Kasus_TBC = format(Kasus_TBC, big.mark = "."),
        Prevalensi = round(Prevalensi, 2),
        Attack_Rate = round(Attack_Rate, 3),
        Rumah_Layak_Pct = round(Rumah_Layak_Pct, 2),
        Miskin_Pct = round(Miskin_Pct, 2),
        Kepadatan = round(Kepadatan, 2)
      )
    
    colnames(detail_table) <- c(
      "Wilayah", "Tipe", "Populasi", "Kasus TBC",
      "Prevalensi (/100k)", "Attack Rate (%)",
      "Rumah Layak (%)", "Kemiskinan (%)", "Kepadatan (jiwa/km²)"
    )
    
    datatable(
      detail_table,
      options = list(
        pageLength = 27,
        scrollX = TRUE,
        scrollY = "450px",
        language = list(url = '//cdn.datatables.net/plug-ins/1.10.11/i18n/Indonesian.json')
      ),
      rownames = FALSE
    ) %>%
      formatStyle(
        'Prevalensi (/100k)',
        backgroundColor = styleInterval(c(300, 500, 700),
                                        c('#E8F5E9', '#FFF9C4', '#FFCCBC', '#EF9A9A'))
      ) %>%
      formatStyle(
        'Attack Rate (%)',
        backgroundColor = styleInterval(c(0.3, 0.5, 0.7),
                                        c('#E8F5E9', '#FFF9C4', '#FFCCBC', '#EF9A9A'))
      )
  })

  
  
# ==================== PLOT DISTRIBUSI PER VARIABEL ====================
    # ======== Filter & urutkan data sesuai input ========
    filtered_data <- reactive({
      dat <- data_processed
      
      # Urutkan
      if (input$sort_order == "desc") {
        dat <- dat %>% arrange(desc(Prevalensi))
      } else {
        dat <- dat %>% arrange(Prevalensi)
      }
      
      # Ambil N wilayah teratas
      head(dat, input$top_n)
    })
    
    # ======== Output untuk plot utama ========
    output$dynamic_plot <- renderPlotly({
      req(input$plot_type)
      df <- filtered_data()
      p <- NULL  # inisialisasi plot kosong
      
      # --- Jenis Grafik: Bar Chart Prevalensi ---
      if (input$plot_type == "bar_prev") {
        df_plot <- df %>%
          arrange(
            if (input$sort_order == "desc") desc(Prevalensi) else Prevalensi
          ) %>%
          head(input$top_n)
        
        p <- ggplot(df, aes(x = factor(`Kabupaten Kota`, levels = df$`Kabupaten Kota`),
                            y = Prevalensi, fill = `Kabupaten Kota`)) +
          geom_bar(stat = "identity", show.legend = FALSE) +
          coord_flip() +
          labs(x = "Wilayah", y = "Prevalensi (%)",
               title = paste("Prevalensi TBC di", input$top_n, "Wilayah Teratas")) +
          theme_minimal(base_size = 14)
      }
      
      # --- Scatter Plot: Layak Huni vs Prevalensi ---
      else if (input$plot_type == "scatter_layakhuni") {
        p <- ggplot(df, aes(x = `Rumah Layak Huni`, y = Prevalensi, text = `Kabupaten Kota`)) +
          geom_point(size = 4, color = "#0072B2") +
          labs(x = "Persentase Layak Huni", y = "Prevalensi (%)",
               title = "Hubungan Rumah Layak Huni dan Prevalensi TBC") +
          theme_minimal(base_size = 14)
      }
      
      # --- Scatter Plot: Kepadatan vs Prevalensi ---
      else if (input$plot_type == "scatter_kepadatan") {
        p <- ggplot(df, aes(x = `Kepadatan Penduduk (Jiwa/KM2)`, y = Prevalensi, text = Wilayah)) +
          geom_point(size = 4, color = "#E69F00") +
          labs(x = "Kepadatan Penduduk", y = "Prevalensi (%)",
               title = "Hubungan Kepadatan dan Prevalensi TBC") +
          theme_minimal(base_size = 14)
      }
      
      # --- Scatter Plot: Kemiskinan vs Prevalensi ---
      else if (input$plot_type == "scatter_kemiskinan") {
        p <- ggplot(df, aes(x = `Persentase Penduduk Miskin`, y = Prevalensi, text = Wilayah)) +
          geom_point(size = 4, color = "#D55E00") +
          labs(x = "Persentase Penduduk Miskin", y = "Prevalensi (%)",
               title = "Hubungan Kemiskinan dan Prevalensi TBC") +
          theme_minimal(base_size = 14)
      }
      
      # --- Distribusi Jumlah Kasus ---
      else if (input$plot_type == "dist_kasus") {
        p <- ggplot(df, aes(x = Kasus_TBC)) +
          geom_histogram(fill = "#56B4E9", color = "white", bins = 10) +
          labs(x = "Jumlah Kasus", y = "Frekuensi", title = "Distribusi Jumlah Kasus TBC") +
          theme_minimal(base_size = 14)
      }
      
      # --- Distribusi Kemiskinan ---
      else if (input$plot_type == "dist_kemiskinan") {
        p <- ggplot(df, aes(x = `Persentase Penduduk Miskin`)) +
          geom_histogram(fill = "#E69F00", color = "white", bins = 10) +
          labs(x = "Persentase Penduduk Miskin", y = "Frekuensi",
               title = "Distribusi Persentase Kemiskinan") +
          theme_minimal(base_size = 14)
      }
      
      # --- Distribusi Kepadatan ---
      else if (input$plot_type == "dist_kepadatan") {
        p <- ggplot(df, aes(x = `Kepadatan Penduduk (Jiwa/KM2)`)) +
          geom_histogram(fill = "#009E73", color = "white", bins = 10) +
          labs(x = "Kepadatan Penduduk", y = "Frekuensi",
               title = "Distribusi Kepadatan Penduduk") +
          theme_minimal(base_size = 14)
      }
      
      # --- Distribusi Rumah Layak Huni
      else if (input$plot_type == "dist_rumah") {
        p <- ggplot(df, aes(x = `Rumah Layak Huni`)) +
          geom_histogram(fill = "#D55E00", color = "white", bins = 10) +
          labs(x = "Persentase Rumah Layak Huni", y = "Frekuensi",
               title = "Distribusi Rumah Layak Huni") +
          theme_minimal(base_size = 14)
      }
      
      
      # --- Perbandingan Kota vs Kabupaten ---
      else if (input$plot_type == "compare_type") {
        p <- ggplot(df, aes(x = Tipe, y = Prevalensi, fill = Tipe)) +
          geom_boxplot(show.legend = FALSE) +
          labs(x = "Tipe Wilayah", y = "Prevalensi (%)", title = "Perbandingan Kota dan Kabupaten") +
          theme_minimal(base_size = 14)
      }
      
      # Convert ke Plotly
      ggplotly(p, tooltip = "text")
    })
    
    # ======== Plot tambahan: Top 10 Wilayah ========
    output$plot_top10 <- renderPlotly({
      top10 <- data_processed %>% arrange(desc(Prevalensi)) %>% head(10)
      
      p <- ggplot(top10, aes(x = reorder(Wilayah, Prevalensi), y = Prevalensi, fill = Wilayah)) +
        geom_bar(stat = "identity", show.legend = FALSE) +
        coord_flip() +
        labs(x = "Wilayah", y = "Prevalensi (%)", title = "Top 10 Wilayah dengan Prevalensi Tertinggi") +
        theme_minimal(base_size = 14)
      
      ggplotly(p)
    })
    
    # ======== Plot tambahan: Matriks Korelasi ========
    output$corr_plot <- renderPlot({
      num_cols <- data_processed  %>% select(Prevalensi, Sanitasi, Kepadatan, Kemiskinan, Kasus, RumahLayak)
      corr <- round(cor(num_cols), 2)
      melted <- melt(corr)
      
      ggplot(melted, aes(x = Var1, y = Var2, fill = value)) +
        geom_tile() +
        geom_text(aes(label = value), color = "white", size = 5) +
        scale_fill_gradient2(low = "#56B4E9", high = "#D55E00", mid = "white", midpoint = 0) +
        labs(title = "Matriks Korelasi Antar Variabel", x = "", y = "") +
        theme_minimal(base_size = 14)
    })


# ==================== KORELASI ====================
output$corr_plot <- renderPlot({
  req(filtered_data())
  cor_data <- filtered_data() %>% 
    select(Prevalensi, Rumah_Layak_Pct, Miskin_Pct, Kepadatan) %>%
    na.omit()
  
  if (nrow(cor_data) > 2) {
    cor_matrix <- cor(cor_data)
    
    colnames(cor_matrix) <- c("Prevalensi\nTBC", "Rumah\nLayak (%)", 
                              "Kemiskinan\n(%)", "Kepadatan\nPenduduk")
    rownames(cor_matrix) <- colnames(cor_matrix)
    
    corrplot(
      cor_matrix, 
      method = "color", 
      type = "upper", 
      addCoef.col = "black",
      number.cex = 1.2,
      tl.col = "black", 
      tl.srt = 45,
      tl.cex = 1.1,
      col = colorRampPalette(c("#0D1B2A", "white", "#5DADE2"))(200),
      title = "Matriks Korelasi Antar Variabel", 
      mar = c(0, 0, 2, 0),
      cl.cex = 1,
      addgrid.col = "gray90"
    )
  } else {
    plot.new()
    text(0.5, 0.5, "Data tidak cukup untuk membuat korelasi", cex = 1.5, col = "red")
  }
})

  # --- Peta Distribusi TBC ---
  output$map_tbc <- renderLeaflet({
    req(input$map_variable)
    
    merged <- batas_jabar %>%
      left_join(data_processed, by = c("NAME_2" = "Wilayah_Clean"))
    
    # Ambil kolom yang dipilih user
    val <- merged[[input$map_variable]]
    
    # Konversi ke numeric tanpa hapus titik desimal
    val <- suppressWarnings(as.numeric(val))
    merged$val <- val
    
    # Cek apakah berhasil konversi
    if (all(is.na(val))) {
      showNotification("Variabel tidak bisa dikonversi menjadi numerik.", type = "error")
      return(leaflet() %>% addTiles())
    }
    
    # Buat palette
    pal <- colorNumeric(
      palette = input$map_color,
      domain = val,
      na.color = "transparent"
    )
    
    leaflet(merged) %>%
      addProviderTiles("CartoDB.Positron") %>%
      addPolygons(
        fillColor = ~pal(val),
        color = "white",
        weight = 1,
        opacity = 1,
        fillOpacity = 0.7,
        label = lapply(
          paste0(
            "<b>", merged$NAME_2, "</b><br>",
            input$map_variable, ": ", formatC(merged$val, format = "f", digits = 2, big.mark = ",")
          ),
          HTML
        ),
        labelOptions = labelOptions(
          style = list(
            "font-weight" = "normal",
            padding = "6px 10px",
            "background-color" = "rgba(255,255,255,0.8)",
            "border-radius" = "6px"
          ),
          textsize = "13px",
          direction = "auto",
          opacity = 0.9
        )
      ) %>%
      addLegend(
        pal = pal,
        values = val,
        title = input$map_variable,
        opacity = 0.7
      )
  })
  
  
  # ==================== INTERPRETASI ====================
  output$kesimpulan <- renderUI({
    # pakai data langsung, bukan reactive()
    df <- data_processed
    
    # pastikan kolom utama ada
    req(df$Prevalensi, df$Wilayah_Clean)
    
    # --- Wilayah dengan nilai ekstrem ---
    wilayah_max <- df$Wilayah_Clean[which.max(df$Prevalensi)]
    prev_max <- round(max(df$Prevalensi, na.rm = TRUE), 2)
    wilayah_min <- df$Wilayah_Clean[which.min(df$Prevalensi)]
    prev_min <- round(min(df$Prevalensi, na.rm = TRUE), 2)
    
    # --- Korelasi antar variabel ---
    cor_sanitasi <- if ("Rumah_Layak_Pct" %in% names(df)) round(cor(df$Prevalensi, df$Rumah_Layak_Pct, use = "complete.obs"), 3) else NA
    cor_kemiskinan <- if ("Miskin_Pct" %in% names(df)) round(cor(df$Prevalensi, df$Miskin_Pct, use = "complete.obs"), 3) else NA
    cor_kepadatan <- if ("Kepadatan" %in% names(df)) round(cor(df$Prevalensi, df$Kepadatan, use = "complete.obs"), 3) else NA
    
    # --- Fungsi interpretasi korelasi ---
    interpret_cor <- function(r) {
      if (is.na(r)) return("-")
      abs_r <- abs(r)
      strength <- ifelse(abs_r >= 0.7, "Kuat",
                         ifelse(abs_r >= 0.4, "Sedang", "Lemah"))
      direction <- ifelse(r > 0, "Positif", "Negatif")
      paste(direction, "-", strength)
    }
    
    # --- Rata-rata per tipe wilayah ---
    avg_kota <- if ("Tipe" %in% names(df)) df %>% filter(Tipe == "Kota") %>% summarise(avg = mean(Prevalensi, na.rm = TRUE)) %>% pull(avg) else NA
    avg_kab <- if ("Tipe" %in% names(df)) df %>% filter(Tipe == "Kabupaten") %>% summarise(avg = mean(Prevalensi, na.rm = TRUE)) %>% pull(avg) else NA
    
    # --- Box kesimpulan ---
    box(width = 12, status = "info", solidHeader = TRUE,
        title = "Kesimpulan & Rekomendasi",
        HTML(paste0(
          "<div style='padding: 15px;'>",
          "<h3 style='color: #0D1B2A; border-bottom: 2px solid #0D1B2A; padding-bottom: 10px;'>Temuan Utama</h3>",
          
          "<div style='background: #E8F4F8; padding: 15px; border-radius: 5px; margin: 15px 0;'>",
          "<h4 style='color: #0D1B2A;'>Gambaran Umum</h4>",
          "<ul style='line-height: 1.8;'>",
          "<li><strong>Total Populasi:</strong> ", format(sum(df$Populasi, na.rm = TRUE), big.mark = "."), " jiwa</li>",
          "<li><strong>Total Kasus TBC:</strong> ", format(sum(df$Kasus_TBC, na.rm = TRUE), big.mark = "."), " kasus</li>",
          "<li><strong>Crude Prevalence Rate:</strong> ",
          round((sum(df$Kasus_TBC, na.rm = TRUE) / sum(df$Populasi, na.rm = TRUE)) * 100000, 2),
          " per 100.000 penduduk</li>",
          "<li><strong>Prevalensi Rata-rata:</strong> ", round(mean(df$Prevalensi, na.rm = TRUE), 2), " per 100.000 penduduk</li>",
          "</ul>",
          "</div>",
          
          "<div style='background: #FFE8E8; padding: 15px; border-radius: 5px; margin: 15px 0;'>",
          "<h4 style='color: #C62828;'>Wilayah Prioritas</h4>",
          "<ul style='line-height: 1.8;'>",
          "<li><strong>Prevalensi Tertinggi:</strong> <span style='color: #C62828; font-weight: bold;'>",
          wilayah_max, "</span> (", prev_max, " per 100.000)</li>",
          "<li><strong>Prevalensi Terendah:</strong> <span style='color: #2E7D32; font-weight: bold;'>",
          wilayah_min, "</span> (", prev_min, " per 100.000)</li>",
          "</ul>",
          "</div>",
          
          "<div style='background: #F3E5F5; padding: 15px; border-radius: 5px; margin: 15px 0;'>",
          "<h4 style='color: #0D1B2A;'>Perbandingan Tipe Wilayah</h4>",
          "<ul style='line-height: 1.8;'>",
          "<li><strong>Prevalensi Rata-rata Kota:</strong> ", round(avg_kota, 2), "</li>",
          "<li><strong>Prevalensi Rata-rata Kabupaten:</strong> ", round(avg_kab, 2), "</li>",
          "</ul>",
          "</div>",
          
          "<div style='background: #FFF9E6; padding: 15px; border-radius: 5px; margin: 15px 0;'>",
          "<h4 style='color: #0D1B2A;'>Analisis Faktor Risiko</h4>",
          "<table style='width:100%; border-collapse: collapse;'>",
          "<tr style='background:#FFF; border-bottom:2px solid #0D1B2A;'>",
          "<th style='padding:10px;'>Variabel</th>",
          "<th style='padding:10px;'>Korelasi</th>",
          "<th style='padding:10px;'>Interpretasi</th></tr>",
          
          if (!is.na(cor_sanitasi))
            paste0("<tr><td>Rumah Layak Huni</td><td>", cor_sanitasi, "</td><td>", interpret_cor(cor_sanitasi), "</td></tr>"),
          if (!is.na(cor_kemiskinan))
            paste0("<tr><td>Kemiskinan</td><td>", cor_kemiskinan, "</td><td>", interpret_cor(cor_kemiskinan), "</td></tr>"),
          if (!is.na(cor_kepadatan))
            paste0("<tr><td>Kepadatan Penduduk</td><td>", cor_kepadatan, "</td><td>", interpret_cor(cor_kepadatan), "</td></tr>"),
          "</table>",
          "</div>",
          "</div>"
        ))
    )
  })
  
}
  
  
  


shinyApp(ui = ui, server = server)

DAFTAR PUSTAKA

  1. World Health Organization. (2023). Global Tuberculosis Report 2023. Geneva: WHO.

  2. Kementerian Kesehatan RI. (2024). Profil Kesehatan Indonesia 2023. Jakarta: Kemenkes RI.

  3. Dinas Kesehatan Provinsi Jawa Barat. (2024). Profil Kesehatan Provinsi Jawa Barat Tahun 2023. Bandung: Dinkes Jabar.

  4. Pai, M., Behr, M. A., Dowdy, D., et al. (2016). Tuberculosis. Nature Reviews Disease Primers, 2, 16076.

  5. Harling, G., & Castro, M. C. (2014). A spatial analysis of social and economic determinants of tuberculosis in Brazil. Health & Place, 25, 56-67.

  6. Anselin, L. (1995). Local Indicators of Spatial Association—LISA. Geographical Analysis, 27(2), 93-115.

  7. Getis, A., & Ord, J. K. (1992). The Analysis of Spatial Association by Use of Distance Statistics. Geographical Analysis, 24(3), 189-206.

  8. Badan Pusat Statistik Provinsi Jawa Barat. (2024). Jawa Barat Dalam Angka 2024. Bandung: BPS Jabar.

  9. Kementerian Kesehatan RI. (2024). Sistem Informasi Tuberkulosis (SITB). Diakses dari: https://sitb.kemkes.go.id

  10. Global Database on Administrative Areas (GADM). Indonesia Administrative Boundaries. Diakses dari: https://gadm.org/

  11. Rothman, K. J., Greenland, S., & Lash, T. L. (2008). Modern Epidemiology (3rd ed.). Philadelphia: Lippincott Williams & Wilkins.

  12. Pfeiffer, D., Robinson, T., Stevenson, M., et al. (2008). Spatial Analysis in Epidemiology. Oxford: Oxford University Press.

  13. Bivand, R. S., Pebesma, E., & Gómez-Rubio, V. (2013). Applied Spatial Data Analysis with R (2nd ed.). New York: Springer.

  14. Bivand, R., & Wong, D. W. S. (2018). Comparing implementations of global and local indicators of spatial association. TEST, 27(3), 716-748.

  15. Pebesma, E. (2018). Simple Features for R: Standardized Support for Spatial Vector Data. The R Journal, 10(1), 439-446.

  16. Tennekes, M. (2018). tmap: Thematic Maps in R. Journal of Statistical Software, 84(6), 1-39.