Abstrak
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.
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:
Bagaimana tren kematian akibat TB paru BTA positif di Puskesmas Kota Bandung selama periode 2015–2024?
Bagaimana distribusi kematian TB paru BTA positif menurut wilayah (kecamatan) dan fasilitas pelayanan kesehatan (Puskesmas) di Kota Bandung?
Faktor-faktor epidemiologis apa yang diduga berkontribusi terhadap tingginya angka kematian TB paru BTA positif di beberapa wilayah atau fasilitas tertentu?
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?
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:
Menggambarkan tren tahunan kematian TB Paru BTA positif di Puskesmas Kota Bandung selama periode 2015–2024.
Mengidentifikasi distribusi spasial kematian TB Paru BTA positif berdasarkan wilayah kecamatan dan fasilitas pelayanan kesehatan.
Menganalisis pola epidemiologis kematian TB Paru BTA positif berdasarkan aspek orang, tempat, dan waktu untuk menemukan perbedaan atau konsentrasi kasus di wilayah tertentu.
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.
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.
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.
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:
| 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 |
Alur kerja analitik terdiri atas tahapan berikut.
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
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))
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.
\[ M_{TB} = \frac{D_{TB}}{P} \times 100{,}000 \]
dengan \(D_{TB}\) adalah jumlah kematian TB per tahun dan \(P\) adalah populasi pertengahan tahun.
\[ CFR = \frac{D_{TB}}{C_{TB}} \times 100\% \]
dengan \(C_{TB}\) adalah jumlah kasus TB yang dilaporkan pada tahun yang sama.
\[ \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\% \]
Untuk menilai faktor risiko kematian, disiapkan kerangka analisis asosiasi menggunakan desain case–control atau cohort. Rumus ukuran asosiasi disajikan sebagai berikut.
\[ 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 |
\[ 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.
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 : …………..
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
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 : ………………
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 : ………….
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
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.
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.
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
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).
## 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.
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.
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
# ==============================
# 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)
| 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)
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)
| 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)
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)
| 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 |
# === 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)
| 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 |
# === 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)
# === 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")
}
| tahun | kemendagri_nama_kecamatan | kasus | jumlah_penduduk | attack_rate_per_100k |
|---|---|---|---|---|
| 2023 | GEDEBAGE | 511 | 2569107 | 19.89018 |
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)
| 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.
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
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