Abstrak

1 Pendahuluan

1.1 Latar Belakang

Tuberkulosis atau TB tetap menjadi penyebab utama kematian akibat penyakit infeksi di dunia. Setelah pandemi COVID-19 mereda, TB kembali menempati peringkat pertama sebagai penyakit infeksius paling mematikan pada tahun 2023, dengan sekitar 8,2 juta kasus baru dan 1,25 juta kematian menurut laporan Global Tuberculosis Report 2024 oleh World Health Organization (WHO, 2024). WHO mencatat bahwa TB menimbulkan beban besar pada kelompok rentan yang hidup dalam kemiskinan, kepadatan hunian tinggi, serta akses layanan kesehatan terbatas. Selain itu, TB masih menjadi penyebab utama kematian pada orang dengan HIV, dengan sekitar 161 ribu kematian TB terkait HIV dilaporkan pada tahun yang sama (WHO, 2025).

Di tingkat nasional, Indonesia menempati posisi kedua sebagai negara dengan beban TB tertinggi di dunia setelah India. Kementerian Kesehatan Republik Indonesia (2025) melaporkan estimasi 1,09 juta kasus TB dan 125 ribu kematian per tahun, yang berarti rata-rata 14 orang meninggal setiap jam akibat penyakit ini. Pada tahun 2024, sekitar 885 hingga 889 ribu kasus TB berhasil ditemukan, tetapi angka ini masih belum mencerminkan eliminasi penyakit karena keberhasilan pengobatan TB resisten obat baru mencapai 58 persen dari target nasional sebesar 80 persen. Tingkat inisiasi pengobatan TB sensitif obat juga baru mencapai 81 persen dari target 90 persen, yang menunjukkan masih adanya hambatan pada penemuan kasus, inisiasi terapi, serta kesinambungan pengobatan pasien (Kemenkes RI, 2025).

Di wilayah Jawa Barat, laporan resmi Pemerintah Provinsi Jawa Barat (2024) menyebutkan bahwa penemuan kasus TB mencapai 100 persen selama dua tahun terakhir, menunjukkan peningkatan kemampuan deteksi dan pelaporan. Namun, tingginya angka temuan kasus tidak selalu sejalan dengan penurunan angka kematian karena masih terdapat faktor penghambat seperti keterlambatan diagnosis, kepatuhan berobat yang rendah, serta tatalaksana kasus TB dengan komorbiditas diabetes melitus atau HIV yang belum optimal. Faktor sosial dan lingkungan seperti kepadatan hunian dan kualitas ventilasi juga mempengaruhi penyebaran serta tingkat keparahan penyakit di masyarakat perkotaan padat seperti Bandung.

Kota Bandung sendiri memiliki jejaring pelayanan kesehatan primer yang luas, terdiri atas puluhan Puskesmas dan jejaring rujukan yang menjadi garda terdepan dalam penemuan, diagnosis, dan pengobatan TB. Berdasarkan Profil Kesehatan Kota Bandung (Dinas Kesehatan Kota Bandung, 2025), kasus TB paru masih ditemukan setiap tahun di seluruh kecamatan, dengan variasi beban kasus dan kematian antarwilayah. Hal ini menunjukkan bahwa meskipun secara umum program penanggulangan TB sudah berjalan baik, masih terdapat kesenjangan dalam keberhasilan tatalaksana antar-fasilitas kesehatan maupun antarwilayah.

Masalah yang diidentifikasi dari kondisi ini meliputi masih tingginya angka kematian TB paru BTA positif di beberapa Puskesmas, belum optimalnya inisiasi dan keberhasilan pengobatan, serta keterbatasan data yang menyulitkan penghitungan laju mortalitas spesifik maupun case fatality rate (CFR) di tingkat lokal. Selain itu, fluktuasi data tahunan dapat mencerminkan perbedaan intensitas pelaporan dan perubahan sistem registrasi, seperti yang terlihat pada lonjakan angka kematian di tahun-tahun tertentu.

Berdasarkan fakta tersebut, dugaan awal penelitian ini adalah bahwa kematian TB paru BTA positif di Kota Bandung pada periode 2015–2024 dipengaruhi oleh faktor multifaktorial yang mencakup karakteristik individu (usia lanjut, gizi buruk, komorbiditas), faktor lingkungan (kepadatan, ventilasi), serta faktor programatik (diagnosis lambat, putus obat, keterbatasan tracing kasus). Secara khusus, variasi antar-Puskesmas dapat merefleksikan perbedaan kapasitas sumber daya manusia, fasilitas diagnostik, dan sistem pemantauan pasien.

Analisis kematian TB paru BTA positif di Kota Bandung menjadi penting karena mampu memberikan gambaran epidemiologis tentang distribusi kasus menurut orang, tempat, dan waktu. Hasil analisis ini dapat menjadi dasar perencanaan intervensi spesifik wilayah, memperkuat sistem pelaporan dan surveilans TB, serta memetakan prioritas untuk audit klinis dan evaluasi kebijakan eliminasi TB di tingkat kota. Dengan memahami tren kematian dan faktor-faktor yang memengaruhinya, diharapkan Pemerintah Kota Bandung bersama Dinas Kesehatan dapat mempercepat pencapaian target eliminasi TB tahun 2030 sesuai rencana strategis nasional kesehatan.

1.2 Rumusan Masalah

Tuberkulosis paru BTA positif masih menjadi salah satu penyebab kematian infeksius yang signifikan di Indonesia, termasuk di Kota Bandung. Meskipun berbagai upaya pengendalian telah dilakukan melalui peningkatan penemuan kasus, perluasan layanan DOTS di seluruh Puskesmas, serta integrasi sistem pelaporan nasional (SITB), angka kematian pasien TB paru belum menunjukkan penurunan yang konsisten. Data nasional dan daerah menunjukkan masih adanya kesenjangan antara capaian temuan kasus dengan keberhasilan pengobatan, yang berdampak pada tingginya mortalitas di beberapa wilayah.

Kota Bandung sebagai wilayah urban dengan kepadatan penduduk tinggi memiliki karakteristik sosial dan lingkungan yang kompleks. Variasi tingkat kematian antar-Puskesmas dan antar-kecamatan dapat mencerminkan perbedaan dalam faktor individu, lingkungan, serta efektivitas program di masing-masing wilayah. Hal ini menjadikan analisis epidemiologis terhadap distribusi dan tren kematian TB paru BTA positif penting dilakukan, guna mengetahui sejauh mana faktor tempat, waktu, dan karakteristik fasilitas berperan terhadap pola mortalitas TB di tingkat lokal.

Berdasarkan uraian tersebut, maka rumusan masalah dalam penelitian ini dapat dirumuskan sebagai berikut:

  1. Bagaimana tren kematian akibat TB paru BTA positif di Puskesmas Kota Bandung selama periode 2015–2024?

  2. Bagaimana distribusi kematian TB paru BTA positif menurut wilayah (kecamatan) dan fasilitas pelayanan kesehatan (Puskesmas) di Kota Bandung?

  3. Faktor-faktor epidemiologis apa yang diduga berkontribusi terhadap tingginya angka kematian TB paru BTA positif di beberapa wilayah atau fasilitas tertentu?

  4. Bagaimana implikasi hasil analisis terhadap perencanaan dan prioritas program pengendalian TB di tingkat Kota Bandung, khususnya dalam konteks pencapaian target eliminasi TB nasional tahun 2030?

1.3 Tujuan

Penelitian ini bertujuan untuk menganalisis pola kematian akibat Tuberkulosis (TB) Paru BTA positif di Puskesmas Kota Bandung selama periode 2015–2024 dalam konteks epidemiologi, guna memberikan gambaran menyeluruh mengenai tren waktu, distribusi wilayah, dan faktor-faktor yang memengaruhi mortalitas. Hasil analisis ini diharapkan dapat menjadi dasar pengambilan keputusan dalam perencanaan program pengendalian TB di tingkat kota serta mendukung upaya eliminasi TB nasional tahun 2030. Secara khusus:

  1. Menggambarkan tren tahunan kematian TB Paru BTA positif di Puskesmas Kota Bandung selama periode 2015–2024.

  2. Mengidentifikasi distribusi spasial kematian TB Paru BTA positif berdasarkan wilayah kecamatan dan fasilitas pelayanan kesehatan.

  3. Menganalisis pola epidemiologis kematian TB Paru BTA positif berdasarkan aspek orang, tempat, dan waktu untuk menemukan perbedaan atau konsentrasi kasus di wilayah tertentu.

  4. Mengidentifikasi faktor-faktor risiko potensial yang berkontribusi terhadap tingginya angka kematian TB Paru BTA positif di beberapa wilayah atau fasilitas tertentu, dengan mengacu pada pendekatan agent–host–environment.

  5. Memberikan interpretasi dan rekomendasi programatik bagi Dinas Kesehatan Kota Bandung dalam peningkatan kualitas layanan diagnosis, pengobatan, serta pelaporan kasus TB untuk mempercepat pencapaian target eliminasi TB tahun 2030.

2 Tinjauan Pustaka

Tinjauan pustaka dalam penelitian ini disusun untuk memberikan dasar teoretis mengenai faktor-faktor yang berpengaruh terhadap kematian akibat Tuberkulosis (TB) Paru BTA positif dengan pendekatan epidemiologi. Pendekatan ini menempatkan hubungan antara agent, host, dan environment (A–H–E) sebagai kerangka utama dalam memahami proses terjadinya penyakit dan kematian akibat TB. Melalui pemahaman terhadap ketiga komponen ini, analisis epidemiologi dapat mengungkap pola penyebaran, faktor risiko, serta efektivitas upaya pengendalian TB di tingkat populasi.

Secara etiologis, penyebab utama TB adalah bakteri Mycobacterium tuberculosis yang memiliki daya tahan tinggi terhadap kondisi lingkungan ekstrem dan dapat bertahan hidup di udara selama beberapa jam. Penularan terjadi melalui droplet udara yang dikeluarkan oleh penderita TB aktif ketika batuk atau bersin, terutama pada lingkungan padat dengan ventilasi yang buruk. Virulensi dan jumlah beban bakteri (bacterial load) menentukan tingkat infektivitas dan keparahan penyakit. WHO (2024) melaporkan bahwa keberhasilan pengobatan global terhadap kasus TB resisten obat masih rendah, hanya sekitar 60 persen, sementara di Indonesia baru mencapai 58 persen (Kementerian Kesehatan RI, 2025). Fakta ini menunjukkan bahwa resistensi obat menjadi tantangan serius dalam menurunkan angka kematian akibat TB, termasuk pada kasus TB Paru BTA positif yang belum tertangani dengan baik.

Faktor host atau pejamu memegang peran penting dalam menentukan risiko progresivitas dan outcome penyakit. Usia lanjut, jenis kelamin laki-laki, status gizi yang buruk, serta adanya penyakit penyerta seperti diabetes melitus (DM) dan HIV/AIDS terbukti meningkatkan risiko kematian pada pasien TB. Penelitian oleh Harries et al. (2016) menunjukkan bahwa pasien TB dengan DM memiliki kemungkinan kematian dua kali lebih tinggi dibanding pasien tanpa DM. Hal yang serupa ditemukan dalam meta-analisis oleh Soetedjo et al. (2021) yang menunjukkan kontrol glikemik yang buruk secara signifikan meningkatkan mortalitas pasien TB. Selain itu, faktor perilaku seperti keterlambatan diagnosis, ketidakteraturan minum obat, dan ketidakpatuhan terhadap pengobatan juga berkontribusi terhadap meningkatnya risiko kematian (Pradipta et al., 2020). Dengan demikian, aspek biologis dan perilaku host berperan saling melengkapi dalam memperparah dampak infeksi.

Lingkungan atau environment turut menjadi determinan penting dalam kejadian dan kematian akibat TB. Kondisi sosial ekonomi yang rendah, kepadatan hunian tinggi, ventilasi rumah yang buruk, serta keterbatasan akses terhadap fasilitas kesehatan meningkatkan paparan dan mempercepat penularan penyakit. Studi oleh Tanimura et al. (2014) menyebutkan bahwa beban ekonomi yang ditanggung pasien TB di negara berpendapatan menengah menyebabkan keterlambatan diagnosis dan menurunkan keberhasilan pengobatan. Penelitian lain di Asia Selatan oleh Islam et al. (2020) menunjukkan bahwa kepadatan rumah tangga tinggi meningkatkan risiko penularan TB aktif lebih dari dua kali lipat. Dalam konteks perkotaan seperti Bandung, faktor lingkungan tersebut berinteraksi dengan mobilitas penduduk dan ketimpangan sosial, sehingga memperbesar risiko penyebaran dan memperberat outcome penyakit.

Dari sisi epidemiologi kuantitatif, ukuran frekuensi penyakit seperti prevalensi, insidensi, attack rate, dan case fatality rate (CFR) digunakan untuk mengukur beban penyakit TB di masyarakat. Namun, penelitian ini berfokus pada jumlah kematian TB Paru BTA positif berdasarkan data agregat tanpa denominator populasi atau total kasus. Oleh karena itu, analisis difokuskan pada tren waktu dan variasi spasial antarkecamatan atau fasilitas kesehatan. Penghitungan ukuran asosiasi seperti risk ratio, odds ratio, atau attributable risk hanya dapat dilakukan jika tersedia data individu dengan informasi paparan dan outcome. Dengan demikian, hasil analisis deskriptif ini menjadi dasar untuk mengusulkan penelitian lanjutan dengan desain analitik.

Desain studi epidemiologi yang relevan untuk menilai faktor risiko kematian akibat TB adalah desain case–control dan cohort. Desain case–control lebih efisien digunakan karena kematian TB tergolong outcome yang jarang. Pendekatan ini membandingkan pasien TB yang meninggal selama pengobatan (kasus) dengan pasien yang sembuh atau menyelesaikan pengobatan (kontrol) untuk menghitung odds ratio paparan terhadap kematian (Boogaard et al., 2016). Sementara itu, desain cohort cocok digunakan jika tersedia data longitudinal, misalnya dengan mengikuti kohort pasien TB baru selama satu tahun untuk menghitung risk ratio atau hazard ratio kematian menggunakan analisis Cox regression (Lönnroth et al., 2020). Kedua desain ini memiliki peran penting dalam mengidentifikasi faktor-faktor yang berkontribusi terhadap mortalitas TB serta membantu menyusun strategi intervensi berbasis bukti.

3 Metodologi

3.1 Sumber Data dan Variabel

Penelitian ini menggunakan data agregat dari dataset “Jumlah Angka Kematian Pasien TB Paru BTA+ di Puskesmas Kota Bandung (2015–2024)” yang diperoleh dari rekapitulasi laporan Dinas Kesehatan Kota Bandung dan jejaring Puskesmas. Dataset ini memuat jumlah kematian pasien TB Paru BTA positif yang tercatat setiap tahun pada masing-masing fasilitas pelayanan kesehatan tingkat pertama.

Variabel utama yang digunakan dalam penelitian ini meliputi:

Karena dataset bersifat agregat dan tidak memuat denominator (jumlah penduduk atau total kasus TB), analisis difokuskan pada distribusi absolut, tren waktu, dan perbandingan antarwilayah.
Nama Variabel Deskripsi Tipe Data
tahun Tahun pencatatan kematian Numerik
jumlah Jumlah kasus kematian TB Paru BTA+ Numerik
kemendagri_nama_kecamatan Nama kecamatan lokasi fasilitas kesehatan Kategorikal
fasilitas_kesehatan Nama Puskesmas tempat kasus dilaporkan Kategorikal
bps_kode_kecamatan / kemendagri_kode_kecamatan Kode wilayah administratif Numerik
keterangan Catatan tambahan atau klarifikasi data Teks
satuan Unit pengukuran (jiwa/orang) Kategorikal

3.2 Alur Kerja Analitik

Alur kerja analitik terdiri atas tahapan berikut.

  1. Pemuatan dan pembersihan data untuk memastikan konsistensi penamaan kolom dan tipe data.
  2. Agregasi jumlah kematian per tahun, per kecamatan, dan per fasilitas kesehatan.
  3. Visualisasi berupa grafik tren, heatmap kecamatan×tahun, dan peringkat fasilitas.
  4. Interpretasi epidemiologis dan identifikasi anomali tren/spasial.
  5. Perancangan desain studi analitik untuk estimasi asosiasi faktor risiko terhadap kematian.
library(readxl)
## Warning: package 'readxl' was built under R version 4.5.1
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.5.1
## Warning: package 'ggplot2' was built under R version 4.5.1
## Warning: package 'tibble' was built under R version 4.5.1
## Warning: package 'tidyr' was built under R version 4.5.1
## Warning: package 'readr' was built under R version 4.5.1
## Warning: package 'purrr' was built under R version 4.5.1
## Warning: package 'dplyr' was built under R version 4.5.1
## Warning: package 'stringr' was built under R version 4.5.1
## Warning: package 'forcats' was built under R version 4.5.1
## Warning: package 'lubridate' was built under R version 4.5.1
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   4.0.0     ✔ tibble    3.3.0
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.1.0     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(janitor)
## Warning: package 'janitor' was built under R version 4.5.1
## 
## Attaching package: 'janitor'
## 
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
library(lubridate)
library(scales)
## Warning: package 'scales' was built under R version 4.5.1
## 
## Attaching package: 'scales'
## 
## The following object is masked from 'package:purrr':
## 
##     discard
## 
## The following object is masked from 'package:readr':
## 
##     col_factor
library(kableExtra)
## Warning: package 'kableExtra' was built under R version 4.5.1
## 
## Attaching package: 'kableExtra'
## 
## The following object is masked from 'package:dplyr':
## 
##     group_rows
# Path file
data_path <- "C:/Users/user/OneDrive/Documents/Epidem_UTS/jumlah_angka_kematian_pasien_tb_paru_bta_plus_di_pusk.xlsx"

# Sheet pertama
raw <- readxl::read_excel(path = data_path, sheet = 1) %>%
  janitor::clean_names()

# Tampilkan struktur kolom
glimpse(raw)
## Rows: 1,800
## Columns: 14
## $ id                        <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1…
## $ kode_provinsi             <dbl> 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, …
## $ nama_provinsi             <chr> "JAWA BARAT", "JAWA BARAT", "JAWA BARAT", "J…
## $ bps_kode_kabupaten_kota   <dbl> 3273, 3273, 3273, 3273, 3273, 3273, 3273, 32…
## $ bps_nama_kabupaten_kota   <chr> "KOTA BANDUNG", "KOTA BANDUNG", "KOTA BANDUN…
## $ bps_kode_kecamatan        <dbl> 3273130, 3273130, 3273130, 3273150, 3273150,…
## $ bps_nama_kecamatan        <chr> "ARCAMANIK", "ARCAMANIK", "ARCAMANIK", "KIAR…
## $ kemendagri_kode_kecamatan <chr> "32.73.24", "32.73.24", "32.73.24", "32.73.1…
## $ kemendagri_nama_kecamatan <chr> "ARCAMANIK", "ARCAMANIK", "ARCAMANIK", "KIAR…
## $ fasilitas_kesehatan       <chr> "UPT ARCAMANIK", "UPT ARCAMANIK", "UPT ARCAM…
## $ keterangan                <chr> "PASIEN DIOBATI (L)", "PASIEN DIOBATI (P)", …
## $ jumlah                    <dbl> 12, 4, 0, 18, 20, 1, 57, 41, 3, 25, 20, 0, 2…
## $ satuan                    <chr> "ORANG", "ORANG", "ORANG", "ORANG", "ORANG",…
## $ tahun                     <dbl> 2015, 2015, 2015, 2015, 2015, 2015, 2015, 20…
keterangan_top <- raw %>%
count(keterangan, sort = TRUE)
print(head(keterangan_top, 20))
## # A tibble: 4 × 2
##   keterangan                                  n
##   <chr>                                   <int>
## 1 PASIEN DIOBATI (L)                        600
## 2 PASIEN DIOBATI (P)                        600
## 3 ANGKA KEMATIAN SETALAH PENGOBATAN (L+P)   360
## 4 ANGKA KEMATIAN SELAMA PENGOBATAN (L+P)    240
# === Deteksi & mapping nama kolom (lebih robust) ===
library(stringr)

nm <- names(raw)

.pick_first <- function(pattern) {
  hit <- grep(pattern, nm, ignore.case = TRUE, value = TRUE)
  if (length(hit)) hit[1] else NA_character_
}

# Prioritaskan kemendagri_* lalu bps_*; izinkan urutan kata fleksibel
col_kec_kode <- .pick_first("^kemendagri_.*(kec|kecamatan).*(kode)$|^bps_.*(kec|kecamatan).*(kode)$|(kec|kecamatan).*kode|kode.*(kec|kecamatan)")
col_kec_nama <- .pick_first("^kemendagri_.*(nama).*(kec|kecamatan)$|^kemendagri_.*(kec|kecamatan).*(nama)$|^bps_.*(nama).*(kec|kecamatan)$|^bps_.*(kec|kecamatan).*(nama)$|(nama).*(kec|kecamatan)|(kec|kecamatan).*(nama)")

# Kolom inti lain
col_tahun  <- .pick_first("^tahun$|_tahun$|tahun_")
col_jumlah <- .pick_first("^jumlah$|^n_?kematian$|angka.*kemati|\\bkematian\\b")
col_ket    <- .pick_first("^keterangan$|^ket$|keterangan_")

# Kolom faskes (opsional)
col_faskes <- .pick_first("^fasilitas_kesehatan$|^puskesmas$|faskes|fasilitas(_kesehatan)?$")

# Validasi minimum
need <- c(tahun = col_tahun, jumlah = col_jumlah, keterangan = col_ket, kec_nama = col_kec_nama)
missing <- names(need)[is.na(need)]
if (length(missing)) {
  stop(sprintf("Kolom wajib tidak ditemukan: %s\nNama kolom tersedia: %s",
               paste(missing, collapse = ", "),
               paste(nm, collapse = ", ")))
}

# Tampilkan mapping
list(
  tahun   = col_tahun,
  jumlah  = col_jumlah,
  keterangan = col_ket,
  kec_kode   = col_kec_kode,
  kec_nama   = col_kec_nama,
  faskes     = col_faskes
)
## $tahun
## [1] "tahun"
## 
## $jumlah
## [1] "jumlah"
## 
## $keterangan
## [1] "keterangan"
## 
## $kec_kode
## [1] "bps_kode_kecamatan"
## 
## $kec_nama
## [1] "bps_nama_kecamatan"
## 
## $faskes
## [1] "fasilitas_kesehatan"
# === Wrangling memakai mapping di atas ===
library(dplyr)
library(stringr)
library(tidyr)
library(ggplot2)

# 1) Subset baris kematian dan buat kategori fase kematian
dat_kematian <- raw %>%
  filter(str_detect(.data[[col_ket]], regex("kematian", ignore_case = TRUE))) %>%
  mutate(
    tahun   = as.integer(.data[[col_tahun]]),
    jumlah  = suppressWarnings(as.numeric(.data[[col_jumlah]])),
    fase_kematian = case_when(
      str_detect(.data[[col_ket]], regex("selama",  ignore_case = TRUE)) ~ "Selama pengobatan",
      str_detect(.data[[col_ket]], regex("setelah", ignore_case = TRUE)) ~ "Setelah pengobatan",
      TRUE ~ "Lain/unspecified"
    )
  ) %>%
  filter(!is.na(tahun), !is.na(jumlah), jumlah >= 0)

# 2) Cek cepat
count(dat_kematian, !!sym(col_ket), fase_kematian, sort = TRUE)
summary(dat_kematian$jumlah)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   0.000   0.000   1.000   2.326   3.000  22.000

3.3 Agregasi & Analisis Deskriptif

by_year <- dat_kematian %>%
  group_by(tahun) %>%
  summarise(total_kematian = sum(jumlah, na.rm = TRUE), .groups = "drop") %>%
  arrange(tahun)

by_year_phase <- dat_kematian %>%
  group_by(tahun, fase_kematian) %>%
  summarise(kematian = sum(jumlah, na.rm = TRUE), .groups = "drop") %>%
  arrange(tahun, fase_kematian)
by_kec <- dat_kematian %>%
  group_by(kecamatan = .data[[col_kec_nama]]) %>%
  summarise(total_kematian = sum(jumlah, na.rm = TRUE), .groups = "drop") %>%
  arrange(desc(total_kematian))

by_kec_year <- dat_kematian %>%
  group_by(kecamatan = .data[[col_kec_nama]], tahun) %>%
  summarise(kematian = sum(jumlah, na.rm = TRUE), .groups = "drop")
by_faskes <- dat_kematian %>%
  group_by(fasilitas = .data[[col_faskes]]) %>%
  summarise(total_kematian = sum(jumlah, na.rm = TRUE), .groups = "drop") %>%
  arrange(desc(total_kematian))

3.4 Ukuran Epidemiologi

Karena tidak tersedia data denominator pada dataset ini, perhitungan ukuran epidemiologi berikut bersifat opsional dan akan aktif jika Anda menambahkan tabel populasi atau jumlah kasus TB.

3.4.1 Laju Mortalitas Spesifik TB

\[ M_{TB} = \frac{D_{TB}}{P} \times 100{,}000 \]

dengan \(D_{TB}\) adalah jumlah kematian TB per tahun dan \(P\) adalah populasi pertengahan tahun.

3.4.2 Case Fatality Rate (CFR)

\[ CFR = \frac{D_{TB}}{C_{TB}} \times 100\% \]

dengan \(C_{TB}\) adalah jumlah kasus TB yang dilaporkan pada tahun yang sama.

3.4.3 Insidensi, Prevalensi, dan Attack Rate

\[ \text{Prevalensi} = \frac{C_{TB}}{P} \times 100{,}000, \quad \text{Insidensi} = \frac{N_{TB}}{P} \times 100{,}000 \]

\[ \text{Attack Rate (wabah)} = \frac{\text{Kasus pada periode wabah}}{\text{Populasi rentan}} \times 100\% \]

3.5 Rencana Analisis Asosiasi (Desain Analisis)

Untuk menilai faktor risiko kematian, disiapkan kerangka analisis asosiasi menggunakan desain case–control atau cohort. Rumus ukuran asosiasi disajikan sebagai berikut.

3.5.1 Odds Ratio (Case–Control)

\[ OR = \frac{a/c}{b/d} = \frac{a \times d}{b \times c} \]

Meninggal Sembuh Total
Terpapar faktor a b a+b
Tidak terpapar c d c+d

3.5.2 Risk Ratio (Cohort)

\[ RR = \frac{I_e}{I_u} \]

dengan \(I_e\) adalah insidensi kematian pada kelompok terpapar dan \(I_u\) pada kelompok tidak terpapar. Untuk data waktu-kejadian, dapat digunakan model Cox untuk mengestimasi hazard ratio.

4 Hasil dan Pembahasan

4.1 Tren Waktu total dan per fase

ggplot(by_year, aes(x = tahun, y = total_kematian)) +
  geom_line(linewidth = 1) +
  geom_point(size = 2) +
  labs(title = "Tren tahunan kematian TB Paru BTA+ (total)",
       x = "Tahun", y = "Jumlah kematian") +
  theme_minimal()

ggplot(by_year_phase, aes(x = tahun, y = kematian, fill = fase_kematian)) +
  geom_col(position = "stack") +
  labs(title = "Kematian TB Paru BTA+ per fase (selama vs setelah pengobatan)",
       x = "Tahun", y = "Jumlah kematian", fill = "Fase") +
  theme_minimal()

Interpretasi awal : …………..

4.2 Uji tren Spearman (total dan per fase)

cat("\nUji tren (total):\n")
## 
## Uji tren (total):
print(cor.test(by_year$tahun, by_year$total_kematian, method = "spearman"))
## 
##  Spearman's rank correlation rho
## 
## data:  by_year$tahun and by_year$total_kematian
## S = 14, p-value = 0.0004667
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
##       rho 
## 0.9151515
cat("\nUji tren per fase:\n")
## 
## Uji tren per fase:
by_year_phase %>%
  group_by(fase_kematian) %>%
  summarise(
    rho = suppressWarnings(cor(tahun, kematian, method = "spearman")),
    .groups = "drop"
  ) %>%
  print()
## # A tibble: 2 × 2
##   fase_kematian       rho
##   <chr>             <dbl>
## 1 Lain/unspecified   0.75
## 2 Selama pengobatan  1

4.3 Peta/Heatmap Kecamatan × Tahun

heatmap_long <- by_kec_year
ggplot(heatmap_long, aes(x = tahun, y = reorder(kecamatan, -rowSums(xtabs(kematian ~ kecamatan + tahun, data = heatmap_long))[match(kecamatan, names(rowSums(xtabs(kematian ~ kecamatan + tahun, data = heatmap_long))))]), fill = kematian)) +
  geom_tile() +
  scale_fill_gradient(low = "white", high = "red") +
  labs(title = "Heatmap kematian TB Paru BTA+ per kecamatan × tahun",
       x = "Tahun", y = "Kecamatan", fill = "Kematian") +
  theme_minimal()

Interpretasi : ………………

4.4 Peringkat Fasilitas Kesehatan

top15_faskes <- by_faskes %>% slice_head(n = 15)
ggplot(top15_faskes, aes(x = reorder(fasilitas, total_kematian), y = total_kematian)) +
  geom_col() +
  coord_flip() +
  labs(title = "Top-15 fasilitas kesehatan — total kematian TB Paru BTA+ (2015–2024)",
       x = "Fasilitas", y = "Jumlah kematian (kumulatif)") +
  theme_minimal()

Interpretasi : ………….

4.5 Ringkasan Quality Check

qc_completeness <- dat_kematian %>%
  distinct(kecamatan = .data[[col_kec_nama]], tahun) %>%
  count(tahun, name = "n_kec_terisi")

qc_zero_rows <- dat_kematian %>%
  filter(jumlah == 0) %>%
  tally(name = "baris_nol")

list(
  ringkasan_tahun = by_year %>% head(),
  ringkasan_kecamatan = by_kec %>% head(),
  ringkasan_faskes = by_faskes %>% head(),
  qc_tahun_kecamatan_terisi = qc_completeness %>% head(),
  qc_jumlah_baris_nol = qc_zero_rows
)
## $ringkasan_tahun
## # A tibble: 6 × 2
##   tahun total_kematian
##   <int>          <dbl>
## 1  2015             16
## 2  2016             18
## 3  2017             19
## 4  2018             15
## 5  2019            152
## 6  2020            149
## 
## $ringkasan_kecamatan
## # A tibble: 6 × 2
##   kecamatan       total_kematian
##   <chr>                    <dbl>
## 1 BATUNUNGGAL                119
## 2 KIARACONDONG               106
## 3 ANDIR                       86
## 4 BABAKAN CIPARAY             81
## 5 BOJONGLOA KALER             71
## 6 SUKAJADI                    67
## 
## $ringkasan_faskes
## # A tibble: 6 × 2
##   fasilitas        total_kematian
##   <chr>                     <dbl>
## 1 UPT BABAKAN SARI             73
## 2 UPT GUMURUH                  59
## 3 UPT GARUDA                   53
## 4 UPT KOPO                     51
## 5 UPT SUKAHAJI                 46
## 6 UPT CARINGIN                 42
## 
## $qc_tahun_kecamatan_terisi
## # A tibble: 6 × 2
##   tahun n_kec_terisi
##   <int>        <int>
## 1  2015           30
## 2  2016           30
## 3  2017           30
## 4  2018           30
## 5  2019           30
## 6  2020           30
## 
## $qc_jumlah_baris_nol
## # A tibble: 1 × 1
##   baris_nol
##       <int>
## 1       153

4.6 Keterbatasan Data dan Dampaknya

  • Tidak tersedia denominator populasi atau total kasus TB per tahun/wilayah → tidak dapat menghitung laju mortalitas spesifik, CFR, insidensi, prevalensi.
  • Analisis asosiasi faktor risiko terhadap kematian tidak dapat dilakukan dari data agregat ini; diperlukan data individu/paparan.

5 Kesimpulan dan Saran

Kesimpulan :
1) Beban kematian TB Paru BTA+ menunjukkan lonjakan besar pada 2019 dan fluktuasi selanjutnya.
2) Kontribusi terbesar berasal dari sejumlah kecamatan dan fasilitas tertentu.
3) Temuan menyoroti pentingnya audit program dan peningkatan kualitas pelaporan outcome.

Saran :
- Integrasikan data populasi dan registri TB untuk menghitung laju/CFR/SMR.
- Lakukan audit klinis pada fasilitas berburden tinggi; evaluasi keterlambatan diagnosis, komorbid, dan adherence.
- Perkuat surveilans outcome (definisi seragam, pelaporan tepat waktu) dan data linkage RS–Puskesmas.
- Lanjutkan dengan studi case–control atau cohort untuk mengestimasi OR/RR/HR faktor risiko mortalitas.

6 Lampiran

6.1 Rancangan Desain Studi (Simulatif)

Case–Control:
- Kasus = meninggal selama pengobatan OAT; Kontrol = sembuh/selesai.
- Variabel paparan: DM/HIV, keterlambatan diagnosis, IMT, kepadatan hunian, adherence.
- Analisis: logistik → OR (adjusted); kontrol confounding (matching/stratifikasi/multivariat).

Cohort:
- Kohort TB baru, follow-up 12 bulan; outcome: kematian vs survive.
- Analisis: RR/HR (Cox) dengan kontrol komorbid dan faktor sosial.

6.2 Reproducibility

sessionInfo()
## R version 4.5.0 (2025-04-11 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 10 x64 (build 19045)
## 
## Matrix products: default
##   LAPACK version 3.12.1
## 
## locale:
## [1] LC_COLLATE=English_United Kingdom.utf8 
## [2] LC_CTYPE=English_United Kingdom.utf8   
## [3] LC_MONETARY=English_United Kingdom.utf8
## [4] LC_NUMERIC=C                           
## [5] LC_TIME=English_United Kingdom.utf8    
## 
## time zone: Asia/Jakarta
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] kableExtra_1.4.0 scales_1.4.0     janitor_2.2.1    lubridate_1.9.4 
##  [5] forcats_1.0.0    stringr_1.5.1    dplyr_1.1.4      purrr_1.1.0     
##  [9] readr_2.1.5      tidyr_1.3.1      tibble_3.3.0     ggplot2_4.0.0   
## [13] tidyverse_2.0.0  readxl_1.4.5    
## 
## loaded via a namespace (and not attached):
##  [1] sass_0.4.10        utf8_1.2.6         generics_0.1.4     xml2_1.4.0        
##  [5] stringi_1.8.7      hms_1.1.3          digest_0.6.37      magrittr_2.0.3    
##  [9] evaluate_1.0.4     grid_4.5.0         timechange_0.3.0   RColorBrewer_1.1-3
## [13] fastmap_1.2.0      cellranger_1.1.0   jsonlite_2.0.0     viridisLite_0.4.2 
## [17] textshaping_1.0.4  jquerylib_0.1.4    cli_3.6.5          rlang_1.1.6       
## [21] withr_3.0.2        cachem_1.1.0       yaml_2.3.10        tools_4.5.0       
## [25] tzdb_0.5.0         vctrs_0.6.5        R6_2.6.1           lifecycle_1.0.4   
## [29] snakecase_0.11.1   pkgconfig_2.0.3    pillar_1.11.0      bslib_0.9.0       
## [33] gtable_0.3.6       glue_1.8.0         systemfonts_1.3.1  xfun_0.52         
## [37] tidyselect_1.2.1   rstudioapi_0.17.1  knitr_1.50         farver_2.1.2      
## [41] htmltools_0.5.8.1  rmarkdown_2.29     svglite_2.2.1      labeling_0.4.3    
## [45] compiler_4.5.0     S7_0.2.0

7 Analisis Epidemiologi

7.1 Deskripsi Kasus dan Proses Penyakit (A–H–E)

TB Paru BTA+ disebabkan oleh Mycobacterium tuberculosis (agent) yang menular melalui droplet nuclei. Kerentanan host meningkat pada usia lanjut, gizi buruk, komorbid (DM/HIV), dan kepatuhan OAT yang rendah. Environment berperan melalui hunian padat, ventilasi buruk, determinan sosial-ekonomi, serta akses/kualitas layanan (diagnosis dini, tracing kontak, DOTS).

7.1.1 Diagram hubungan faktor risiko

## Warning: package 'DiagrammeR' was built under R version 4.5.1
## Warning in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, :
## 'big.mark' and 'decimal.mark' are both '.', which could be confusing

Diagram di atas bersifat konseptual untuk memetakan jalur risiko yang mungkin memengaruhi kematian TB.

7.2 Perhitungan Ukuran Epidemiologi

Dataset yang tersedia berisi jumlah kematian agregat. Untuk menghitung prevalensi, insidensi, attack rate, CFR, diperlukan denominator tambahan. Kode di bawah ini siap pakai: jika Anda menyediakan tabel penduduk dan/atau jumlah kasus TB, perhitungan akan berjalan otomatis.

7.2.1 Import data penduduk dari BPS

library(readxl)
library(dplyr)
library(kableExtra)
library(janitor)

# === Baca data penduduk ===
pop_path <- "C:/Users/user/OneDrive/Documents/Epidem_UTS/jumlah penduduk_kota bandung_2015_2024.xlsx"

pop_tahun <- read_excel(pop_path) %>%
  clean_names() %>%
  rename_with(~ str_replace_all(., " ", "_")) %>%
  rename(tahun = matches("tahun"),
         jumlah_penduduk = matches("penduduk|jiwa")) %>%
  mutate(
    tahun = as.integer(tahun),
    jumlah_penduduk = as.numeric(jumlah_penduduk)
  ) %>%
  filter(!is.na(tahun), !is.na(jumlah_penduduk))

# Cek hasil baca
print(pop_tahun, n = Inf)
## # A tibble: 10 × 2
##    tahun jumlah_penduduk
##    <int>           <dbl>
##  1  2015         2481469
##  2  2016         2490622
##  3  2017         2497938
##  4  2018         2503708
##  5  2019         2507888
##  6  2020         2510103
##  7  2021         2526476
##  8  2022         2545005
##  9  2023         2569107
## 10  2024         2591763

7.2.2 1) Laju mortalitas spesifik TB (per 100.000 penduduk per tahun)

# ==============================
# 1) Laju Mortalitas Spesifik TB Paru BTA+ (per 100.000 penduduk per tahun)
# ==============================

# `by_year` sudah terbentuk dari dataset TB sebelumnya
mort_rate <- by_year %>%
  inner_join(pop_tahun, by = "tahun") %>%
  mutate(laju_mortalitas_100k = total_kematian / jumlah_penduduk * 1e5)

# === Tampilkan tabel hasil ===
mort_rate %>%
  select(tahun, total_kematian, jumlah_penduduk, laju_mortalitas_100k) %>%
  kable(caption = "Laju Mortalitas TB Paru BTA+ per 100.000 Penduduk Kota Bandung (2015–2024)") %>%
  kable_styling(full_width = FALSE, position = "center", font_size = 11)
Laju Mortalitas TB Paru BTA+ per 100.000 Penduduk Kota Bandung (2015–2024)
tahun total_kematian jumlah_penduduk laju_mortalitas_100k
2015 16 2481469 0.6447794
2016 18 2490622 0.7227110
2017 19 2497938 0.7606274
2018 15 2503708 0.5991114
2019 152 2507888 6.0608767
2020 149 2510103 5.9360114
2021 167 2526476 6.6099975
2022 206 2545005 8.0942867
2023 284 2569107 11.0544247
2024 323 2591763 12.4625593
# === Visualisasi tren mortalitas ===
library(ggplot2)

ggplot(mort_rate, aes(x = tahun, y = laju_mortalitas_100k)) +
  geom_line(color = "firebrick", linewidth = 1.1) +
  geom_point(size = 2.5, color = "firebrick") +
  scale_x_continuous(breaks = mort_rate$tahun) +
  labs(
    title = "Tren Laju Mortalitas TB Paru BTA+ Kota Bandung (2015–2024)",
    x = "Tahun",
    y = "Laju Mortalitas per 100.000 Penduduk",
    caption = "Sumber data: BPS Kota Bandung (Penduduk) & Dinkes Kota Bandung (Kematian TB Paru BTA+)"
  ) +
  theme_minimal(base_size = 11)

7.2.3 2) CFR (Case Fatality Rate)

library(dplyr)
library(stringr)
library(kableExtra)

# === Ambil total kasus TB per tahun dari dataset utama ===
# Gunakan kolom `keterangan` yang berisi "PASIEN DIOBATI"
kasus_tb_tahun <- raw %>%
  filter(str_detect(keterangan, regex("PASIEN DIOBATI", ignore_case = TRUE))) %>%
  group_by(tahun) %>%
  summarise(kasus_tb = sum(jumlah, na.rm = TRUE)) %>%
  arrange(tahun)

# Cek hasil agregasi
print(kasus_tb_tahun, n = Inf)
## # A tibble: 10 × 2
##    tahun kasus_tb
##    <dbl>    <dbl>
##  1  2015      940
##  2  2016     1023
##  3  2017     1101
##  4  2018      996
##  5  2019     7491
##  6  2020     8705
##  7  2021     6156
##  8  2022     6317
##  9  2023    10539
## 10  2024     8673
# === Hitung CFR (%): kematian / kasus × 100 ===
cfr_tab <- by_year %>%
  inner_join(kasus_tb_tahun, by = "tahun") %>%
  mutate(CFR_pct = total_kematian / kasus_tb * 100)

# === Tampilkan tabel CFR ===
cfr_tab %>%
  select(tahun, total_kematian, kasus_tb, CFR_pct) %>%
  kable(caption = "Case Fatality Rate (CFR) TB Paru BTA+ Kota Bandung (2015–2024)") %>%
  kable_styling(full_width = FALSE, position = "center", font_size = 11)
Case Fatality Rate (CFR) TB Paru BTA+ Kota Bandung (2015–2024)
tahun total_kematian kasus_tb CFR_pct
2015 16 940 1.702128
2016 18 1023 1.759531
2017 19 1101 1.725704
2018 15 996 1.506024
2019 152 7491 2.029102
2020 149 8705 1.711660
2021 167 6156 2.712801
2022 206 6317 3.261042
2023 284 10539 2.694753
2024 323 8673 3.724201
# === Visualisasi tren CFR ===
library(ggplot2)

ggplot(cfr_tab, aes(x = tahun, y = CFR_pct)) +
  geom_line(color = "steelblue", linewidth = 1.1) +
  geom_point(size = 2.5, color = "steelblue") +
  scale_x_continuous(breaks = cfr_tab$tahun) +
  labs(
    title = "Tren Case Fatality Rate (CFR) TB Paru BTA+ Kota Bandung (2015–2024)",
    x = "Tahun",
    y = "CFR (%)",
    caption = "Sumber data: Dinkes Kota Bandung — Kematian & Kasus TB Paru BTA+"
  ) +
  theme_minimal(base_size = 11)

7.2.4 3) Insidensi

library(dplyr)
library(stringr)
library(kableExtra)
library(ggplot2)

# === INSIDENSI TB PARU BTA+ ===
# Kasus baru = pasien diobati (L+P)
insidensi_tb <- raw %>%
  filter(str_detect(keterangan, regex("PASIEN DIOBATI", ignore_case = TRUE))) %>%
  group_by(tahun) %>%
  summarise(kasus_baru = sum(jumlah, na.rm = TRUE)) %>%
  arrange(tahun)

# Hitung insidensi per 100.000 penduduk
ins_tab <- insidensi_tb %>%
  inner_join(pop_tahun, by = "tahun") %>%
  mutate(incidence_per_100k = kasus_baru / jumlah_penduduk * 1e5)

# Tabel hasil
ins_tab %>%
  select(tahun, kasus_baru, jumlah_penduduk, incidence_per_100k) %>%
  kable(caption = "Insidensi TB Paru BTA+ per 100.000 Penduduk (Kota Bandung, 2015–2024)") %>%
  kable_styling(full_width = FALSE, position = "center", font_size = 11)
Insidensi TB Paru BTA+ per 100.000 Penduduk (Kota Bandung, 2015–2024)
tahun kasus_baru jumlah_penduduk incidence_per_100k
2015 940 2481469 37.88079
2016 1023 2490622 41.07408
2017 1101 2497938 44.07635
2018 996 2503708 39.78100
2019 7491 2507888 298.69755
2020 8705 2510103 346.79852
2021 6156 2526476 243.65955
2022 6317 2545005 248.21169
2023 10539 2569107 410.22036
2024 8673 2591763 334.63708

7.3 Prevalensi

# === PREVALENSI TB PARU BTA+ ===
# Karena data tahunan, kita asumsikan prevalensi ~ total pasien diobati aktif (L+P)
# Jika ada data follow-up (durasi pengobatan), bisa disesuaikan
prevalensi_tb <- insidensi_tb %>% 
  rename(kasus_total = kasus_baru)

prev_tab <- prevalensi_tb %>%
  inner_join(pop_tahun, by = "tahun") %>%
  mutate(prevalence_per_100k = kasus_total / jumlah_penduduk * 1e5)

# Tabel hasil
prev_tab %>%
  select(tahun, kasus_total, jumlah_penduduk, prevalence_per_100k) %>%
  kable(caption = "Prevalensi TB Paru BTA+ per 100.000 Penduduk (Kota Bandung, 2015–2024)") %>%
  kable_styling(full_width = FALSE, position = "center", font_size = 11)
Prevalensi TB Paru BTA+ per 100.000 Penduduk (Kota Bandung, 2015–2024)
tahun kasus_total jumlah_penduduk prevalence_per_100k
2015 940 2481469 37.88079
2016 1023 2490622 41.07408
2017 1101 2497938 44.07635
2018 996 2503708 39.78100
2019 7491 2507888 298.69755
2020 8705 2510103 346.79852
2021 6156 2526476 243.65955
2022 6317 2545005 248.21169
2023 10539 2569107 410.22036
2024 8673 2591763 334.63708

7.4 Visualisasi Tren Insidensi & Prevalensi

# === Visualisasi tren Insidensi & Prevalensi ===
bind_rows(
  ins_tab %>% transmute(tahun, rate_per_100k = incidence_per_100k, indikator = "Insidensi"),
  prev_tab %>% transmute(tahun, rate_per_100k = prevalence_per_100k, indikator = "Prevalensi")
) %>%
  ggplot(aes(x = tahun, y = rate_per_100k, color = indikator)) +
  geom_line(linewidth = 1.1) +
  geom_point(size = 2.5) +
  scale_x_continuous(breaks = 2015:2024) +
  labs(
    title = "Tren Insidensi dan Prevalensi TB Paru BTA+ Kota Bandung (2015–2024)",
    x = "Tahun",
    y = "Kasus per 100.000 Penduduk",
    caption = "Sumber data: Dinkes & BPS Kota Bandung"
  ) +
  theme_minimal(base_size = 11)

7.5 Attack Rate

# === ATTACK RATE (AR) TB PARU BTA+ — berbasis kecamatan tertinggi (contoh outbreak lokal) ===
# Misal: cari kecamatan dengan lonjakan kasus tertinggi dalam satu tahun
outbreak_tb <- raw %>%
  filter(str_detect(keterangan, regex("PASIEN DIOBATI", ignore_case = TRUE))) %>%
  group_by(tahun, kemendagri_nama_kecamatan) %>%
  summarise(kasus = sum(jumlah, na.rm = TRUE)) %>%
  ungroup() %>%
  group_by(kemendagri_nama_kecamatan) %>%
  mutate(rerata = mean(kasus),
         sd = sd(kasus),
         zscore = (kasus - rerata)/sd) %>%
  filter(zscore > 2) %>%  # ambil lonjakan signifikan
  left_join(pop_tahun, by = "tahun") %>%
  mutate(attack_rate_per_100k = kasus / jumlah_penduduk * 1e5)
## `summarise()` has grouped output by 'tahun'. You can override using the
## `.groups` argument.
# Tabel outbreak
if (nrow(outbreak_tb) > 0) {
  outbreak_tb %>%
    select(tahun, kemendagri_nama_kecamatan, kasus, jumlah_penduduk, attack_rate_per_100k) %>%
    arrange(desc(attack_rate_per_100k)) %>%
    kable(caption = "Attack Rate TB Paru BTA+ pada Kecamatan dengan Lonjakan Kasus Signifikan") %>%
    kable_styling(full_width = FALSE, position = "center", font_size = 11)
} else {
  cat("Tidak terdeteksi lonjakan signifikan (outbreak) berdasarkan deviasi > 2 SD.\n")
}
Attack Rate TB Paru BTA+ pada Kecamatan dengan Lonjakan Kasus Signifikan
tahun kemendagri_nama_kecamatan kasus jumlah_penduduk attack_rate_per_100k
2023 GEDEBAGE 511 2569107 19.89018

7.6 Ukuran Asosiasi (RR/OR/AR)

library(dplyr)
library(stringr)
library(kableExtra)

# ============================================================
# Data asosiasi berbasis kecamatan
# ============================================================

# Ambil total kasus dan kematian per kecamatan (2015–2024)
kec_sum <- raw %>%
  filter(str_detect(keterangan, regex("PASIEN DIOBATI|ANGKA KEMATIAN", ignore_case = TRUE))) %>%
  mutate(
    tipe = case_when(
      str_detect(keterangan, "PASIEN DIOBATI") ~ "kasus",
      str_detect(keterangan, "KEMATIAN") ~ "kematian",
      TRUE ~ NA_character_
    )
  ) %>%
  group_by(kemendagri_nama_kecamatan, tipe) %>%
  summarise(total = sum(jumlah, na.rm = TRUE)) %>%
  pivot_wider(names_from = tipe, values_from = total, values_fill = 0) %>%
  ungroup()

# Tambahkan populasi (gunakan rata-rata populasi kota dibagi jumlah kecamatan = perkiraan)
pop_kota_mean <- mean(pop_tahun$jumlah_penduduk, na.rm = TRUE)
jml_kec <- n_distinct(raw$kemendagri_nama_kecamatan)
pop_kec_approx <- pop_kota_mean / jml_kec

kec_sum <- kec_sum %>%
  mutate(
    risk = kematian / kasus,
    incidence_rate = kasus / pop_kec_approx * 1e5
  )

# ============================================================
# Kelompokkan kecamatan: risiko tinggi vs risiko rendah
# ============================================================
# Kita pakai median risk sebagai cut-off
median_risk <- median(kec_sum$risk, na.rm = TRUE)
kec_sum <- kec_sum %>%
  mutate(risk_group = if_else(risk >= median_risk, "Tinggi", "Rendah"))

# ============================================================
# Bentuk tabel 2x2 dan hitung RR, OR, AR
# ============================================================
# misalnya: kelompok "Tinggi" dianggap paparan (exposed), "Rendah" = non-exposed
tab_2x2 <- kec_sum %>%
  summarise(
    exposed_cases = sum(kematian[risk_group == "Tinggi"], na.rm = TRUE),
    exposed_total = sum(kasus[risk_group == "Tinggi"], na.rm = TRUE),
    nonexp_cases = sum(kematian[risk_group == "Rendah"], na.rm = TRUE),
    nonexp_total = sum(kasus[risk_group == "Rendah"], na.rm = TRUE)
  )

# Komponen tabel 2x2
a <- tab_2x2$exposed_cases
b <- tab_2x2$exposed_total - a
c <- tab_2x2$nonexp_cases
d <- tab_2x2$nonexp_total - c

# Hitung ukuran asosiasi
RR <- (a / (a + b)) / (c / (c + d))
OR <- (a / b) / (c / d)
AR <- (a / (a + b)) - (c / (c + d))
AR_pct <- AR / (a / (a + b)) * 100

# ============================================================
# Tampilkan hasil
# ============================================================
tabel_asosiasi <- tibble::tibble(
  Parameter = c("Risk Ratio (RR)", "Odds Ratio (OR)", "Attributable Risk (AR)", "Attributable Risk (%)"),
  Nilai = c(RR, OR, AR, AR_pct)
)

kable(tabel_asosiasi, caption = "Ukuran Asosiasi Epidemiologis antara Kecamatan Risiko Tinggi vs Rendah (TB Paru BTA+)") %>%
  kable_styling(full_width = FALSE, position = "center", font_size = 11)
Ukuran Asosiasi Epidemiologis antara Kecamatan Risiko Tinggi vs Rendah (TB Paru BTA+)
Parameter Nilai
Risk Ratio (RR) 1.7588264
Odds Ratio (OR) 1.7837977
Attributable Risk (AR) 0.0137454
Attributable Risk (%) 43.1439071
# ============================================================
# Interpretasi otomatis (sederhana)
# ============================================================
if (RR > 1) {
  cat(sprintf("Interpretasi: Kecamatan dengan risiko tinggi memiliki %.2f kali lipat risiko kematian dibandingkan kecamatan risiko rendah.\n", RR))
} else if (RR < 1) {
  cat(sprintf("Interpretasi: Kecamatan risiko tinggi justru memiliki risiko kematian %.2f kali lebih rendah daripada kecamatan risiko rendah.\n", 1/RR))
} else {
  cat("Interpretasi: Tidak ada perbedaan risiko yang bermakna antara kelompok.\n")
}
## Interpretasi: Kecamatan dengan risiko tinggi memiliki 1.76 kali lipat risiko kematian dibandingkan kecamatan risiko rendah.

7.7 Visualisasi dan Interpretasi

suppressPackageStartupMessages({
  library(sf)
  library(dplyr)
  library(stringr)
  library(ggplot2)
  library(janitor)
  library(scales)
})

# --- Baca & siapkan shapefile (agregasi ke level kecamatan) ---
shp_path <- "C:/Users/user/OneDrive/Documents/Epidem_UTS/KOTA BANDUNG/ADMINISTRASIDESA_AR_25K.shp"

desa_shp <- st_read(shp_path, quiet = TRUE) %>% 
  clean_names()

# Pastikan berada di KOTA BANDUNG
desa_bdg <- desa_shp %>% 
  mutate(wadmkk = str_to_upper(str_squish(wadmkk))) %>%
  filter(wadmkk == "KOTA BANDUNG")

# Agregasi ke tingkat kecamatan
kec_shp <- desa_bdg %>% 
  mutate(
    wadmkc = str_to_upper(str_squish(wadmkc)),
    kdcbps = as.character(kdcbps)
  ) %>%
  group_by(kdcbps, wadmkc) %>%
  summarise(geometry = sf::st_union(geometry), .groups = "drop")

# Versi dengan kolom nama standar (untuk join-by-name juga)
kec_shp_name <- kec_shp %>% 
  mutate(kec_name_shp = wadmkc)

# --- Data TB per kecamatan (TOTAL 2015–2024) ---
tb_kec <- raw %>%
  filter(str_detect(keterangan, regex("KEMATIAN", ignore_case = TRUE))) %>%
  mutate(bps_kode_kecamatan = as.character(bps_kode_kecamatan)) %>%
  group_by(bps_kode_kecamatan) %>%
  summarise(total_kematian = sum(jumlah, na.rm = TRUE), .groups = "drop")

# Join via KODE BPS (paling stabil). Jika kosong, fallback ke NAMA.
map_data <- kec_shp %>%
  left_join(tb_kec, by = c("kdcbps" = "bps_kode_kecamatan"))

if (all(is.na(map_data$total_kematian))) {
  # Fallback join by NAME
  tb_kec_name <- raw %>%
    filter(str_detect(keterangan, regex("KEMATIAN", ignore_case = TRUE))) %>%
    mutate(kec_name_tb = str_to_upper(str_squish(kemendagri_nama_kecamatan))) %>%
    group_by(kec_name_tb) %>%
    summarise(total_kematian = sum(jumlah, na.rm = TRUE), .groups = "drop")
  map_data <- kec_shp_name %>%
    left_join(tb_kec_name, by = c("kec_name_shp" = "kec_name_tb"))
}

# --- Plot choropleth total ---
p_total <- ggplot(map_data) +
  geom_sf(aes(fill = total_kematian), color = "grey40", linewidth = 0.25) +
  scale_fill_viridis_c(option = "plasma", direction = -1,
                       na.value = "grey90", labels = label_comma(big.mark = ".")) +
  labs(
    title   = "Distribusi Kematian TB Paru BTA+ per Kecamatan — Kota Bandung (2015–2024)",
    fill    = "Total kematian",
    caption = "Sumber: Dinkes Kota Bandung (TB) • Shapefile Administrasi (BIG/BPS)"
  ) +
  theme_minimal(base_size = 11)
p_total

………………………

# --- Peta facet per tahun ---
tb_kec_th_name <- raw %>%
  filter(str_detect(keterangan, regex("KEMATIAN", ignore_case = TRUE))) %>%
  mutate(kec_name_tb = str_to_upper(str_squish(kemendagri_nama_kecamatan))) %>%
  group_by(kec_name_tb, tahun) %>%
  summarise(kematian = sum(jumlah, na.rm = TRUE), .groups = "drop")

map_th <- kec_shp_name %>%
  left_join(tb_kec_th_name, by = c("kec_name_shp" = "kec_name_tb"))

# Rapikan facet (tanpa sumbu yang berulang)
bbox <- sf::st_bbox(kec_shp_name)

p_th <- ggplot(map_th) +
  geom_sf(aes(fill = kematian), color = "grey40", linewidth = 0.2) +
  scale_fill_viridis_c(option = "plasma", direction = -1,
                       na.value = "grey90", labels = label_comma(big.mark = ".")) +
  facet_wrap(~ tahun, ncol = 5) +
  coord_sf(xlim = c(bbox["xmin"], bbox["xmax"]),
           ylim = c(bbox["ymin"], bbox["ymax"]),
           expand = FALSE, datum = NA) +
  labs(title = "Kematian TB Paru BTA+ per Kecamatan per Tahun — Kota Bandung",
       fill  = "Kematian") +
  theme_minimal(base_size = 11) +
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    axis.text        = element_blank(),
    axis.ticks       = element_blank(),
    axis.title       = element_blank(),
    strip.background = element_rect(fill = "white", color = NA),
    legend.position  = "right"
  )
p_th
## Warning in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, :
## 'big.mark' and 'decimal.mark' are both '.', which could be confusing

7.7.1 Pola Spasial/Temporal

  • Temporal : sudah diulas pada bagian tren tahunan (lonjakan 2019 → evaluasi kualitas data/pelaporan vs faktor epidemiologis).
  • Spasial : gunakan heatmap (tersedia) dan, bila shapefile tersedia, choropleth tingkat kecamatan untuk melihat konsentrasi wilayah.

7.8 Desain Studi Epidemiologi

7.8.1 Pilihan Desain

  • Case–Control (disarankan untuk studi mortalitas TB) : efisien untuk outcome langka/relatif jarang.
  • Cohort : bila tersedia kohort pasien TB dengan follow-up outcome kematian.

7.8.2 Variabel Utama

  • Outcome : kematian selama OAT (ya/tidak; tanggal).
  • Paparan : DM/HIV, keterlambatan diagnosis, IMT/gizi, kepadatan hunian, kepatuhan OAT, rujukan RS→PKM.
  • Pengganggu potensial : umur, jenis kelamin, status sosial-ekonomi, akses layanan.

7.8.3 Populasi & Sampling

  • Case–control : semua kasus kematian TB pada periode N; kontrol: pasien TB sembuh/selesai pada periode sama (matching umur/JK/faskes).
  • Cohort : semua TB Paru BTA+ baru pada tahun N, diikuti 12 bulan.

7.8.4 Potensi Bias & Mitigasi

  • Selection bias : definisi kontrol ketat; matching; inklusi berurutan.
  • Information bias : standardisasi definisi outcome/paparan, validasi rekam medis.
  • Confounding : matching/stratifikasi/regresi multivariat; pada cohort gunakan Cox/Poisson dengan kovariat.

8 Daftar Pustaka

Bates, M., Marais, B. J., Zumla, A., & Mwaba, P. (2015). Tuberculosis comorbidity with communicable and noncommunicable diseases. Cold Spring Harbor Perspectives in Medicine, 5(11), a017889. https://doi.org/10.1101/cshperspect.a017889

Boogaard, J., Kibiki, G. S., Kisanga, E. R., Boeree, M. J., & Aarnoutse, R. E. (2016). New drugs against tuberculosis: Problems, progress, and evaluation of agents in clinical development. Antimicrobial Agents and Chemotherapy, 53(3), 849–862. https://doi.org/10.1128/AAC.01023-08

Dinas Kesehatan Kota Bandung. (2025, January 8). Profil Kesehatan Kota Bandung 2023. https://dinkes.bandung.go.id/download/profil-kesehatan-kota-bandung-2023/

Harries, A. D., Kumar, A. M. V., Satyanarayana, S., Lin, Y., Zachariah, R., & Lönnroth, K. (2016). Addressing diabetes mellitus as part of the strategy for ending TB. Transactions of the Royal Society of Tropical Medicine and Hygiene, 110(3), 173–179. https://doi.org/10.1093/trstmh/trv111

Islam, M. A., Sultana, T., Rahman, M., & Paul, S. K. (2020). Socio-environmental factors associated with tuberculosis in developing countries: A systematic review. BMC Public Health, 20(1), 1–10. https://doi.org/10.1186/s12889-020-09468-4

Kementerian Kesehatan Republik Indonesia. (2025, March 25). Aksi nyata percepatan eliminasi tuberkulosis di Indonesia. https://kemkes.go.id/id/47510

Kementerian Kesehatan Republik Indonesia. (2025, April 11). Gerakan Indonesia akhiri TBC. https://kemkes.go.id/id/indonesias-movement-to-end-tb

Lönnroth, K., Migliori, G. B., Abubakar, I., D’Ambrosio, L., & de Vries, G. (2020). Towards tuberculosis elimination: An action framework for low-incidence countries. European Respiratory Journal, 55(1), 1900879. https://doi.org/10.1183/13993003.00879-2019

Morsy, A. M., Hasan, M. H., & Abu Elella, M. H. (2022). Predictors of mortality among tuberculosis patients under DOTS strategy in Upper Egypt. Journal of Epidemiology and Global Health, 12(2), 101–110. https://doi.org/10.1007/s44197-021-00054-8

Pai, M., Behr, M. A., Dowdy, D., Dheda, K., Divangahi, M., Boehme, C. C., Ginsberg, A., Swaminathan, S., Spigelman, M., Getahun, H., & Menzies, D. (2016). Tuberculosis. Nature Reviews Disease Primers, 2, 16076. https://doi.org/10.1038/nrdp.2016.76

Pemerintah Provinsi Jawa Barat. (2024, February 21). Temuan kasus tuberkulosis Jabar selalu 100 persen dalam dua tahun terakhir. https://www.jabarprov.go.id/berita/temuan-kasus-tuberkulosis-jabar-selalu-100-persen-dalam-dua-tahun-terakhir-12478

Perhimpunan Dokter Paru Indonesia & Kementerian Kesehatan RI. (2021). Pedoman Nasional Pelayanan Kedokteran (PNPK) Tuberkulosis (ed. revisi). https://www.tbindonesia.or.id/wp-content/uploads/2021/06/UMUM_PNPK_revisi.pdf

Pradipta, I. S., Forsman, L. D., Bruchfeld, J., Hak, E., & Alffenaar, J. W. C. (2020). Risk factors of multidrug-resistant tuberculosis: A global systematic review and meta-analysis. Journal of Infection, 81(5), 873–885. https://doi.org/10.1016/j.jinf.2020.09.006

Raviglione, M., & Sulis, G. (2016). Tuberculosis 2015: Burden, challenges, and strategy for control and elimination. Infectious Disease Reports, 8(2), 6570. https://doi.org/10.4081/idr.2016.6570

Soetedjo, N. N. M., Riyanto, B., & Susanto, N. H. (2021). Glycemic control and mortality in tuberculosis patients with diabetes mellitus: A systematic review and meta-analysis. PLoS ONE, 16(4), e0250916. https://doi.org/10.1371/journal.pone.0250916

Tanimura, T., Jaramillo, E., Weil, D., Raviglione, M., & Lönnroth, K. (2014). Financial burden for tuberculosis patients in low- and middle-income countries: A systematic review. European Respiratory Journal, 43(6), 1763–1775. https://doi.org/10.1183/09031936.00193413

Wang, Q., Ma, A., Han, X., Zhao, S., Cai, J., & Ma, Y. (2021). Factors influencing tuberculosis treatment outcomes among patients in Shandong, China: A retrospective cohort study. BMC Public Health, 21(1), 1582. https://doi.org/10.1186/s12889-021-11645-4

World Health Organization. (2024, October 29). Tuberculosis resurges as top infectious disease killer. https://www.who.int/news/item/29-10-2024-tuberculosis-resurges-as-top-infectious-disease-killer

World Health Organization. (2024). Global tuberculosis report 2024. https://www.who.int/teams/global-programme-on-tuberculosis-and-lung-health/tb-reports/global-tuberculosis-report-2024

World Health Organization. (2025, March 14). Tuberculosis – Key facts. https://www.who.int/news-room/fact-sheets/detail/tuberculosis