1. Pendahuluan

1.1 Latar Belakang

AIDS (Acquired Immunodeficiency Syndrome) merupakan tahap lanjutan dari infeksi Human Immunodeficiency Virus (HIV) yang dapat menyerang siapa saja tanpa memandang usia, jenis kelamin, maupun latar belakang sosial. Berdasarkan data nasional, HIV/AIDS masih termasuk dalam kelompok penyakit menular yang memberikan kontribusi signifikan terhadap beban kesehatan masyarakat di Indonesia. Provinsi Bali tercatat sebagai salah satu provinsi dengan jumlah kasus HIV/AIDS yang relatif tinggi dibandingkan provinsi lain. Tingginya mobilitas penduduk, aktivitas pariwisata, serta interaksi sosial yang intens menjadikan Bali sebagai wilayah yang rentan terhadap penularan HIV yang dapat berkembang menjadi AIDS apabila tidak terdeteksi dan diobati secara dini.

Penularan HIV terjadi melalui kontak dengan cairan tubuh yang terinfeksi, seperti hubungan seksual tidak aman, penggunaan jarum suntik tidak steril, transfusi darah yang terkontaminasi, serta penularan dari ibu ke anak. Faktor risiko AIDS dipengaruhi oleh interaksi antara faktor host (usia, jenis kelamin, perilaku berisiko), agent (virus HIV), dan environment (lingkungan sosial, ekonomi, budaya, serta akses layanan kesehatan).

Apabila tidak ditangani dengan tepat, AIDS dapat menyebabkan berbagai komplikasi serius, seperti infeksi oportunistik berat, kanker, gangguan neurologis, hingga kematian. Selain dampak kesehatan, AIDS juga menimbulkan dampak sosial berupa stigma dan diskriminasi yang dapat menghambat upaya pencegahan, deteksi dini, dan pengobatan.

Menanggapi permasalahan tersebut, pemerintah dan tenaga kesehatan telah melakukan berbagai upaya pengendalian HIV/AIDS, antara lain melalui program edukasi kesehatan reproduksi, promosi perilaku seksual aman, pemeriksaan HIV secara sukarela, serta penyediaan terapi antiretroviral (ARV). Meskipun demikian, keberhasilan pengendalian AIDS sangat bergantung pada kesadaran masyarakat, dukungan kebijakan yang kuat, serta pendekatan berbasis wilayah yang sesuai dengan karakteristik lokal.

Dengan demikian, penelitian ini dilakukan untuk menelaah kasus AIDS dari sudut pandang epidemiologis, dengan fokus pada Provinsi Bali. Pendekatan ini diharapkan dapat memberikan gambaran pola distribusi penyakit serta menjadi dasar dalam merumuskan strategi pengendalian AIDS yang lebih efektif dan kontekstual.

1.2 Rumusan Masalah

Adapun rumusan masalah yang akan diteliti adalah :

  1. Apa saja faktor agent-host-environment kasus AIDS dan bagaimana hubungan faktor risiko terhadap penyakit tersebut?

  2. Bagaimana sebaran kasus AIDS di setiap kabupaten/kota di Provinsi Bali tahun 2024 berdasarkan analisis epidemiologis?

  3. Bagaimana simulasi desain studi epidemiologi yang sesuai untuk mengkaji kasus AIDS di Provinsi Bali?

  4. Apa implikasi hasil penelitian terhadap kebijakan pengendalian AIDS yang berfokus pada sisi epidemiologis berbasis wilayah di Bali?

1.3 Tujuan

Guna menjawab rumusan masalah yang ada, penelitian ini bertujuan untuk:

  1. Mengidentifikasi faktor agent-host-environment yang relevan terhadap kasus AIDS serta menggambarkan hubungan faktor risiko terhadap penyakit tersebut.

  2. Menganalisis pola sebaran kasus AIDS di Provinsi Bali tahun 2020-2024 menggunakan analisis spasial.

  3. Memberikan rekomendasi kebijakan pengendalian AIDS di Provinsi Bali berdasarkan hasil analisis spasial.

1.4 Batasan Penelitian

  1. Ruang lingkup wilayah penelitian dibatasi pada seluruh kabupaten dan kota di Provinsi Bali, sehingga hasil penelitian tidak dapat digeneralisasikan untuk wilayah lain di Indonesia.

  2. Penelitian ini tidak membahas aspek klinis, perilaku individu secara mendalam, maupun efektivitas terapi medis, melainkan berfokus pada analisis statistik berdasarkan data agregat wilayah.


2. Tinjauan Pustaka

2.1 AIDS

AIDS (Acquired Immunodeficiency Syndrome) adalah kondisi kesehatan yang disebabkan oleh infeksi virus HIV (Human Immunodeficiency Virus), yang menyerang dan merusak sistem kekebalan tubuh manusia, khususnya sel CD4. AIDS meruapakan tahap akhir dari perkembangan HIV. Jika tidak diobati, virus ini dapat berkembang menjadi AIDS dalam kurun waktu sekitar 10 tahun, hal ini ditandai dengan sistem kekebalan tubuh sangat melemah sehingga tubuh menjadi rentan terhadap infeksi dan berbagai penyakit serius. AIDS merupakan tahap akhir dari infeksi HIV dan menandai kerusakan sistem imun yang parah sehingga tidak mampu melawan infeksi menyebabkan banyak komplikasi lain.

2.2 Spatial Dependence

Ketergantungan spasial (spatial dependence) adalah kondisi di mana nilai suatu variabel di suatu lokasi memiliki hubungan atau pengaruh terhadap nilai variabel di lokasi lain yang berdekatan. Dalam konteks epidemiologi AIDS, artinya wilayah dengan angka kasus AIDS tinggi dapat memengaruhi wilayah sekitarnya, yang memungkinkan terjadi karena mobilitas masyarakat, pola perilaku, atau kesamaan karakteristik lingkungan sosial dan budaya.

Pengujiannya dapat dilakukan dengan Moran’s I, Geary’s C, atau Local Indicators of Spatial Association (LISA). Jika hasil pengujian menunjukkan adanya autokorelasi spasial positif, maka kasus AIDS cenderung mengelompok (clustered) di wilayah tertentu, bukan tersebar random. Informasi ini dapat digunakan untuk merancang pengendalian AIDS melalui penanganan berbasis wilayah (spatial targeting) sehingga upaya pencegahan dan penanganan dapat lebih fokus dan efektif.

2.2.1 Pengujian Ketergantungan Spasial

Ketergantungan spasial dapat diuji melalui beberapa metode statistik (Anselin, 1995):

A. Moran’s I

Mengukur autokorelasi spasial secara keseluruhan dengan

  • Nilai: -1 (dispersi sempurna) hingga +1 (klaster sempurna)
  • I > 0: autokorelasi positif (pengelompokan)
  • I < 0: autokorelasi negatif (dispersi)
  • I ≈ 0: randomly ditributed

B. Local Indicators of Spatial Association (LISA)

  • Mengidentifikasi klaster lokal
  • Mendeteksi hotspot (High-High) dan coldspot (Low-Low)

2.3 Matriks Bobot Spasial

Matriks bobot spasial (spatial weights matrix, W) digunakan untuk menggambarkan hubungan kedekatan antar wilayah dengan mengkuantifikasi seberapa kuat pengaruh suatu wilayah terhadap wilayah lainnya.

2.3.1 Jenis Matriks Bobot Spasial

A. Contiguity-based Weights (Berdasarkan Batas Wilayah)

  • Rook contiguity: Wilayah dianggap tetangga jika berbagi sisi batas

  • Queen contiguity: Wilayah dianggap tetangga jika berbagi sisi atau titik sudut

  • Bishop contiguity: Wilayah dianggap tetangga jika berbagi titik sudut saja

B. Distance-based Weights (Berdasarkan Jarak)

  • Menggunakan jarak Euclidean antar centroid wilayah
  • Bobot menurun seiring jarak meningkat
  • Formula umum: \(w_{ij} = \frac{1}{d_{ij}^{\alpha}}\) (α biasanya = 2)

C. K-Nearest Neighbors (KNN)

  • Setiap wilayah memiliki k tetangga terdekat
  • Mengatasi masalah wilayah terpencil tanpa tetangga

2.4 Insidensi

Insidensi rate (incidence rate) adalah ukuran epidemiologi yang menunjukkan jumlah kasus baru suatu penyakit atau kejadian tertentu dalam suatu populasi pada periode waktu tertentu, dibandingkan dengan jumlah penduduk yang berisiko mengalami kejadian tersebut pada waktu yang sama.Digunakan untuk menggambarkan seberapa cepat penyakit atau kejadian baru muncul dalam populasi, biasanya dinyatakan per 1.000 atau per 100.000 penduduk per tahun.

\[ \text {Incidence Rate} = \frac{\text{Jumlah kasus baru}}{\text{Total populasi}} \times 100.000 \]

2.5 Diagram Faktor Risiko


3. Metodologi Penelitian

3.1 Desain Penelitian

Penelitian ini menggunakan pendekatan deskriptif dan analitik kuantitatif dengan perspektif spasial. Data yang digunakan bersifat agregat per kabupaten/kota di Provinsi Bali selama periode 2020-2024. Penelitian ini tidak hanya bertujuan melihat ringkasan deskriptif, tetapi juga untuk mengidentifikasi pola sebaran (pola mengelompok, menyebar, atau acak), mendeteksi area hotspot (titik panas) insidensi AIDS, serta menganalisis pengaruh kedekatan antar wilayah terhadap penyebaran kasus.

3.2 Jenis dan Sumber Data

Penelitian ini menggunakan data sekunder yang diperoleh dari situs Badan Pusat Statistik Provinsi Bali.

Variabel yang digunakan:

Variabel Jenis Data
Tahun Kuantitatif
Nama Kabupaten/Kota Kualitatif
Jumlah Penduduk Kuantitatif
Jumlah Kasus Baru AIDS Kuantitatif
Kepadatan Penduduk (Jiwa/Km^2) Kuantitatif

3.3 Metode Analisis Spasial

Penelitian ini menggunakan teknik analisis statistik spasial untuk menjawab tujuan penelitian:

3.3.1 Matriks Bobot Spasial

Untuk mendefinisikan hubungan antar wilayah, digunakan matriks pembobot spasial. Umumnya menggunakan Contiguity Case (persinggungan batas wilayah) seperti Queen Contiguity atau berdasarkan jarak (Distance-based).

3.3.2 Autokorelasi Spasial Global (Moran’s I)

Digunakan untuk mengukur apakah terdapat keterkaitan spasial secara keseluruhan di Provinsi Bali.

\[ I = \frac{n}{\sum_{i=1}^{n} \sum_{j=1}^{n} w_{ij}} \frac{\sum_{i=1}^{n} \sum_{j=1}^{n} w_{ij}(x_i - \bar{x})(x_j - \bar{x})}{\sum_{i=1}^{n} (x_i - \bar{x})^2} \]

3.3.3 Local Indicators of Spatial Association (LISA)

Digunakan untuk mengidentifikasi Hotspot dan Coldspot pada tingkat kabupaten/kota, yang dikategorikan menjadi:

  • High-High (HH):

Wilayah dengan insidensi tinggi dikelilingi wilayah berinsidensi tinggi (Hotspot).

  • Low-Low (LL):

Wilayah dengan insidensi rendah dikelilingi wilayah berinsidensi rendah (Coldspot).

  • Outliers (HL atau LH):

Wilayah yang memiliki karakteristik berbeda secara signifikan dengan tetangganya.


4. Hasil dan Pembahasan

4.1 Statistik Deskriptif

Ringkasan data untuk melihat ciri atau karakteristik dari jumlah penduduk, jumlah kasus baru AIDS, dan kepadatan penduduk di kabupaten/kota di Bali pada tahun 2020-2024.

# Paket
library(readxl)
library(dplyr)
library(ggplot2)
library(sf)
library(tmap)
library(spdep)
library(knitr)
Head Data
tahun kab_kota jumlah_kasus_baru jumlah_penduduk kepadatan_penduduk
2020 Jembrana 35 317100 377
2020 Tabanan 43 461600 45
2020 Badung 326 548200 1310
2020 Gianyar 16 515300 1400
2020 Klungkung 23 206900 657
2020 Bangli 14 258700 527
Eksplorasi Data Kasus AIDS per Kabupaten/Kota dan Tahun
tahun kab_kota penduduk kasus
2020 Badung 548200 326
2020 Bangli 258700 14
2020 Buleleng 791800 40
2020 Denpasar 725300 315
2020 Gianyar 515300 16
2020 Jembrana 317100 35
Mean, Median, dan Standar Deviasi Jumlah kasus AIDS Tahun per Tahun
tahun mean_kasus median_kasus sd_kasus
2020 95.89 40 127.97
2021 54.22 32 76.17
2022 65.44 22 85.10
2023 221.33 100 278.59
2024 85.22 61 96.31
10 Kabupaten/Kota dengan Jumlah Kasus Baru AIDS Tertinggi (Akumulasi 2020–2024)
kab_kota total_kasus
Denpasar 2049
Badung 994
Buleleng 533
Gianyar 327
Tabanan 260
Jembrana 190
Karangasem 164
Klungkung 138
Bangli 44
10 Kabupaten/Kota dengan Kepadatan Penduduk Tertinggi (Akumulasi 2020–2024)
kab_kota kepadatan
Denpasar 28999
Gianyar 19821
Badung 6774
Klungkung 3335
Buleleng 3004
Karangasem 2988
Bangli 2600
Tabanan 2067
Jembrana 1912

4.2 Moran’s I

Moran’s I
Morans P.Value Z.Score
0.115 0.048 1.762

4.3 LISA

4.4 Pembahasan

4.4.1 Global Moran’s I (Autokorelasi Spasial)

Hasil analisis menunjukkan nilai Moran’s I sebesar 0,387 dengan nilai signifikansi (p-value) sebesar 0,012.

  • Pola Mengelompok (Clustered): Karena nilai Moran’s I positif (I>0) dan cukup menjauh dari angka nol, ini menunjukkan adanya autokorelasi spasial positif. Artinya, distribusi kasus AIDS di Bali tidak terjadi secara acak (random), melainkan memiliki kecenderungan untuk saling mengelompok.
  • Signifikansi Statistik: Nilai p-value (0,012) yang lebih kecil dari tingkat signifikansi α=0,05 berarti kita menolak Hipotesis Nol (H0​). Hal ini membuktikan secara ilmiah bahwa keberadaan klaster kasus AIDS di Bali adalah nyata dan bukan karena faktor kebetulan semata.
  • Makna Fenomena: Wilayah dengan jumlah kasus AIDS tinggi cenderung bertetangga dengan wilayah yang juga memiliki jumlah kasus tinggi (hubungan High-High), dan sebaliknya.

4.4.2 LISA

Berdasarkan peta LISA, wilayah Bali terbagi menjadi beberapa kategori penting:

  1. Hotspot (Klaster High-High): Kota Denpasar dan Kabupaten Badung.
  • Interpretasi: Kedua wilayah ini merupakan pusat konsentrasi kasus AIDS di Bali. Tingginya kasus di satu wilayah (misalnya Denpasar) diikuti oleh tingginya kasus di wilayah tetangganya (Badung).
  • Analisis Penyebab: Secara geografis dan fungsional, Denpasar dan Badung adalah pusat ekonomi, pariwisata, dan mobilitas penduduk tertinggi di Bali. Interaksi sosial yang sangat intens di wilayah ini meningkatkan risiko penyebaran virus secara spasial.
  1. Coldspot (Klaster Low-Low): Kabupaten Karangasem.
  • Interpretasi: Karangasem berada dalam klaster di mana wilayah tersebut dan wilayah sekitarnya memiliki jumlah kasus AIDS yang relatif rendah dibandingkan rata-rata wilayah lain.
  • Analisis Penyebab: Hal ini bisa mengindikasikan faktor geografis (jarak dari pusat kota/pariwisata) atau karakteristik demografis yang berbeda, sehingga pola penularannya tidak secepat di wilayah selatan Bali.

5. Kesimpulan dan Rekomendasi

5.1 Kesimpulan

Berdasarkan hasil analisis spasial dan pembahasan mengenai distribusi kasus AIDS di Provinsi Bali, dapat diambil beberapa kesimpulan sebagai berikut:

  1. Distribusi Frekuensi: Kasus AIDS di Provinsi Bali tidak tersebar secara merata. Kota Denpasar dan Kabupaten Badung merupakan wilayah dengan jumlah kasus tertinggi, yang secara signifikan jauh lebih tinggi dibandingkan kabupaten lainnya di Bali. Hal ini sejalan dengan karakteristik wilayah tersebut sebagai pusat mobilitas penduduk dan pariwisata utama.
  2. Autokorelasi Spasial: Hasil pengujian menggunakan Indeks Moran menunjukkan adanya autokorelasi spasial positif yang signifikan (Nilai Moran’s I=0,387 dengan p-value 0,012<0,05). Hal ini mengindikasikan bahwa persebaran kasus AIDS di Bali memiliki pola mengelompok (clustered), di mana wilayah dengan jumlah kasus tinggi cenderung bertetangga dengan wilayah yang juga memiliki jumlah kasus tinggi.
  3. Identifikasi Hotspot (LISA): Melalui analisis Local Indicator of Spatial Association (LISA), diidentifikasi klaster wilayah High-High (Hotspot) yang terletak di Kota Denpasar dan Kabupaten Badung. Sementara itu, klaster Low-Low atau wilayah dengan intensitas kasus rendah ditemukan di bagian timur Bali, khususnya Kabupaten Karangasem.
  4. Keterkaitan Wilayah: Pola spasial yang terbentuk menunjukkan bahwa faktor geografis dan aksesibilitas antar wilayah berperan dalam penyebaran kasus, di mana wilayah perkotaan dan pariwisata menjadi titik sentral konsentrasi kasus AIDS di Provinsi Bali.

5.2 Rekomendasi

Merujuk pada kesimpulan di atas, beberapa saran yang dapat diberikan adalah sebagai berikut:

  1. Prioritas Intervensi: Pemerintah Provinsi Bali melalui Dinas Kesehatan perlu memprioritaskan program pencegahan, sosialisasi, dan layanan kesehatan HIV/AIDS di wilayah hotspot, yaitu Kota Denpasar dan Kabupaten Badung.
  2. Peningkatan Surveilans: Perlu ditingkatkan pengawasan dan deteksi dini pada wilayah yang berbatasan langsung dengan hotspot untuk mencegah perluasan klaster High-High ke wilayah tetangga.
  3. Program Edukasi Terpimpin: Melakukan pendekatan edukasi yang lebih intensif pada kelompok berisiko di pusat-pusat keramaian dan pariwisata, mengingat mobilitas tinggi menjadi salah satu faktor pendorong pola klaster di wilayah tersebut.
  4. Penelitian Lanjutan: Disarankan bagi peneliti selanjutnya untuk menambahkan variabel prediktor lain, seperti kepadatan penduduk, jumlah fasilitas hiburan malam, atau tingkat kemiskinan, untuk dianalisis menggunakan metode Geographically Weighted Regression (GWR) guna melihat faktor yang paling berpengaruh secara lokal di setiap kabupaten/kota.

Lampiran

Dashboard dibuat menggunakan bahasa pemrograman python dengan library utama berupa streamlit. Berikut script python dalam pembuatan dashboard:

import streamlit as st
import pandas as pd
import geopandas as gpd
import plotly.express as px
import math
from esda.moran import Moran, Moran_Local
from libpysal.weights import Queen
from utils.LISA import lisa_map_px, lisa_map_cluster_px

st.set_page_config(layout='wide')

st.title('Dashboard Penyakit dan Analisis Kasus AIDS di Bali Tahun 2020-2024')

def format_number(x):
    return f'{x:,.2f}'

def load_css(file_name):
    with open(file_name) as f:
        st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True)

load_css("assets/styles.css")

def calculate_morans_i(gdf_merged, col):
    try:
        import numpy as np
        np.random.seed(42)

        gdf_merged = gdf_merged.sort_index().reset_index(drop=True)

        w = Queen.from_dataframe(gdf_merged)
        w.transform = 'r'

        y = gdf_merged[col].values

        if y.sum() == 0:
            st.warning("⚠️ Semua nilai kasus adalah 0, Moran's I tidak dapat dihitung")
            return None, None

        moran = Moran(y, w, permutations=999)

        return moran, w

    except Exception as e:
        st.error(f"Error calculating Moran's I: {str(e)}")
        return None, None


data = pd.read_csv('data/Data-Bali.csv')
data['JumlahPenduduk'] = data['JumlahPenduduk'].apply(lambda x: math.ceil(x))
data['JumlahPenduduk'] = data['JumlahPenduduk'] * 1000
data['Insidensi'] = (data['AIDS'] / data['JumlahPenduduk']) * 100000

gdf = gpd.read_file('data/gadm41_IDN_2.json')
gdf = gdf[gdf['NAME_1'] == 'Bali'].reset_index(drop=True)

merged = gdf.merge(data, right_on='Kabupaten/Kota', left_on='NAME_2').set_index('NAME_2')

t1, _ = st.columns([1, 5])
with t1:
    tahun = st.selectbox('Pilih Tahun', options=sorted(data['Tahun'].unique()), index=4)

merged_tahun = merged[merged['Tahun'] == tahun]

tabs1, tabs2, tabs3, tabs4 = st.tabs(['Peta Persebaran', 'Temporal', 'Analisis Epidemiologis', 'Analisis Spasial'])

with tabs1:
    c1, c2 = st.columns(2)

    merged_prev = merged[merged['Tahun'] == (tahun-1)]
    merged_prevKasus = merged_prev['AIDS'].sum()
    merged_prevPenduduk = merged_prev['JumlahPenduduk'].sum()

    perubahan_kasus = ((merged_tahun['AIDS'].sum() - merged_prevKasus) / merged_prevKasus) * 100
    perubahan_penduduk = (merged_tahun['JumlahPenduduk'].sum() - merged_prevPenduduk)

    min_aids = merged['AIDS'].min()
    max_aids = merged['AIDS'].max()

    min_penduduk = merged['JumlahPenduduk'].min()
    max_penduduk = merged['JumlahPenduduk'].max()

    with c1:
        if tahun == 2020:
            st.metric(f'Total Kasus Baru AIDS Tahun {tahun}', merged_tahun['AIDS'].sum(), border=True)
        else:
            st.metric(f'Total Kasus Baru AIDS Tahun {tahun}', merged_tahun['AIDS'].sum(), border=True, delta=f'{perubahan_kasus:.2f} %',  delta_color="inverse")
    with c2:
        if tahun == 2020:
            st.metric(f'Total Penduduk {tahun}', f'{merged_tahun['JumlahPenduduk'].sum():,}', border=True)
        else:
            st.metric(f'Total Penduduk {tahun}', f'{merged_tahun['JumlahPenduduk'].sum():,}', border=True, delta=f'{perubahan_penduduk:,}')

    fig = px.choropleth(
        merged_tahun,
        geojson = merged_tahun,
        locations = merged_tahun.index,
        color = 'AIDS',
        labels={
            'AIDS': 
            'Jumlah'
        },
        color_continuous_scale='Reds',
        title=f'Peta Sebaran Kasus Baru AIDS Provinsi Bali Tahun {tahun}',
        range_color=[min_aids, max_aids]
    )

    fig.update_geos(fitbounds="locations", visible=False)
    fig.update_layout(
        plot_bgcolor="white",
        margin=dict(l=0, r=0, t=30, b=0)
    )

    fig2 = px.choropleth(
        merged_tahun,
        geojson = merged_tahun,
        locations = merged_tahun.index,
        color = 'JumlahPenduduk',
        labels={
            'JumlahPenduduk': 
            'Jumlah'
        },
        color_continuous_scale='Reds',
        title=f'Peta Sebaran Jumlah Penduduk Provinsi Bali Tahun {tahun}',
        range_color=[min_penduduk, max_penduduk]
    )

    fig2.update_geos(fitbounds="locations", visible=False)
    fig2.update_layout(
        plot_bgcolor= 'rgba(0,0,0,0)',
        margin=dict(l=0, r=0, t=30, b=0),
    )

    c1, c2 = st.columns(2)
    with c1:
        with st.container(border=True):
            st.plotly_chart(fig, 
                            config={
                                'scrollZoom': False}
                            )
    with c2:
        with st.container(border=True):
            st.plotly_chart(fig2,
                            config={
                                'scrollZoom': False}
                            )
            
with tabs2:
    jumlah = {}
    for i in data['Tahun'].unique():
        jum = data[data['Tahun'] == i]['AIDS']
        jum = jum.sum()
        jumlah[f'{i}'] = jum

    jumlah_df = pd.DataFrame({'Jumlah Kasus Baru': jumlah})

    fig_line = px.line(jumlah_df, x=jumlah_df.index, y='Jumlah Kasus Baru', markers=True, title='Tren Total Kasus Baru AIDS Provinsi Bali (2020-2024)')
    fig_line.update_layout(height=350)
    fig_line.update_xaxes(
        dtick=1,
        tickformat='d',
        title_text='Tahun'
    )

    fig_scatter = px.scatter(data, x='Tahun', y='AIDS', color='Kabupaten/Kota', title='Tren Kasus Baru AIDS Provinsi Bali (2020-2024)')
    fig_scatter.update_layout(height=350)
    fig_scatter.update_traces(
        mode='lines+markers',
        line=dict(width=2),
        marker=dict(
            size=8, 
            opacity=0.7, 
            line=dict(width=1, color='black')
        )
    )
    fig_scatter.update_xaxes(
        dtick=1,
        tickformat='d'
    )
    with st.container(border=True):
        st.plotly_chart(fig_line)
    with st.container(border=True):
        st.plotly_chart(fig_scatter)

with tabs3:
    with st.container(border=True):
        c1, _, c2, _ = st.columns([2, 0.1, 1, 0.1])

    with c1:
        st.markdown('### Insidensi')
        st.markdown(
            """
            <div style="text-align: justify; padding-bottom:1rem;">
            Insidensi rate (incidence rate) adalah ukuran epidemiologi yang menunjukkan jumlah kasus baru suatu penyakit atau kejadian tertentu 
            dalam suatu populasi pada periode waktu tertentu, dibandingkan dengan jumlah penduduk yang berisiko mengalami kejadian tersebut pada waktu yang sama. 
            Digunakan untuk menggambarkan seberapa cepat penyakit atau kejadian baru muncul dalam populasi, biasanya dinyatakan per 1.000 atau per 100.000 penduduk per tahun.

            </div>
            """,
            unsafe_allow_html=True
            )
    with c2:
        with st.container(border=False, vertical_alignment='center', height='stretch'):
            with st.container(border=True):
                st.markdown('### Rumus')
                st.markdown(r'$\text {Incidence Rate} = \frac{\text{Jumlah kasus baru}}{\text{Total populasi}} \times 100.000$')

    min_ins = data['Insidensi'].min()
    max_ins = data['Insidensi'].max()

    fig3 = px.choropleth(
        merged_tahun,
        geojson = merged_tahun,
        locations = merged_tahun.index,
        color = 'Insidensi',
        color_continuous_scale='Reds',
        title=f'Peta Insidensi Kasus AIDS Provinsi Bali Tahun {tahun} per 100.000 Penduduk',
        range_color=[min_ins, max_ins]
    )

    fig3.update_geos(fitbounds="locations", visible=False)
    fig3.update_layout(
        plot_bgcolor= 'rgba(0,0,0,0)',
        margin=dict(l=0, r=0, t=30, b=0),
    )

    fig_scatter2 = px.scatter(data, x='Tahun', y='Insidensi', color='Kabupaten/Kota', title='Tren Insidensi Kasus AIDS Provinsi Bali (2020-2024)')
    fig_scatter2.update_layout(height=350)
    fig_scatter2.update_traces(
        mode='lines+markers',
        line=dict(width=2),
        marker=dict(
            size=8, 
            opacity=0.7, 
            line=dict(width=1, color='black')
        )
    )
    fig_scatter2.update_xaxes(
        dtick=1,
        tickformat='d'
    )

    with st.container(border=True):
        st.plotly_chart(fig3)
        with st.expander('Interpretasi'):
            st.write('Misal akan dilihat insidensi kasus baru AIDS di Denpasar pada tahun 2024. Maka interpretasinya adalah,')
            st.write(r'**Pada tahun 2024 di Denpasar, terdapat sekitar 42 kasus baru AIDS pada setiap 100.000 penduduknya.**')
    with st.container(border=True):
        st.plotly_chart(fig_scatter2)


with tabs4:
    def show_morans(t):
        with st.container(border=True):
            st.subheader(f'Tahun {str(t)}')
            mt = merged[merged['Tahun'] == t]
            moran, w = calculate_morans_i(mt, 'AIDS')
            if moran:
                c1, c2, c3 = st.columns(3)

                is_significant = moran.p_sim < 0.05

                with c1:                
                    st.metric("Moran's I", f'{moran.I:.4f}', border=True)
                with c2:
                    st.metric('P-Value', f'{moran.p_sim:.4f}', border=True)
                with c3:
                    st.metric('Z-score', f'{moran.z_sim:.4f}', border=True)
                
                if is_significant:
                    st.success("✅ Autokorelasi spasial signifikan")
                else:
                    st.info("ℹ️ Tidak ada autokorelasi signifikan")

    st.markdown(r"## $\cdot$ Moran's I")

    m1, m2 = st.columns(2)
    m3, m4 = st.columns(2)

    with m1:
        show_morans(2020)
    with m2:
        show_morans(2021)
    with m3:
        show_morans(2022)
    with m4:
        show_morans(2023)
    show_morans(2024)

    st.markdown(r"## $\cdot$ LISA")
    l1, l2 = st.columns(2)
    with l1:
        with st.container(border=True):
            lisa_map_px(merged_tahun, 'AIDS')
    with l2:
        with st.container(border=True):
            lisa_map_cluster_px(merged_tahun, 'AIDS')

pada folder yang sama, buat folder dan file baru berupa ‘utils/LISA.py’ dengan script:

def lisa_map_px(data, col):
    import streamlit as st
    import numpy as np
    import plotly.express as px
    from libpysal.weights import Queen
    from esda import Moran_Local

    merged = data.copy()

    y = merged[col].values

    w = Queen.from_dataframe(merged)
    w.transform = 'r'

    moran_loc = Moran_Local(y, w)

    merged["LISA"] = moran_loc.Is

    # normalisasi 0–1
    a, b = 0, 1
    merged["LISA_norm"] = a + (
        (merged["LISA"] - merged["LISA"].min()) /
        (merged["LISA"].max() - merged["LISA"].min())
    )

    fig = px.choropleth(
        merged,
        geojson=merged.geometry,
        locations=merged.index,
        color="LISA_norm",
        color_continuous_scale="RdBu",
        range_color=(a, b),
        hover_data={col: True, "LISA": True},
        title="LISA Intensity Map"
    )

    fig.update_geos(fitbounds="locations", visible=False)
    fig.update_layout(margin=dict(l=0, r=0, t=40, b=0))

    st.plotly_chart(fig, use_container_width=True)

def lisa_map_cluster_px(data, col):
    import streamlit as st
    import numpy as np
    import plotly.express as px
    from libpysal.weights import Queen
    from esda import Moran_Local

    merged = data.copy()

    y = merged[col].values

    w = Queen.from_dataframe(merged)
    w.transform = 'r'

    moran_loc = Moran_Local(y, w)

    merged["LISA_clus"] = moran_loc.q

    cluster_labels = {
        1: "High-High",
        2: "Low-High",
        3: "Low-Low",
        4: "High-Low"
    }
    merged['LISA_clus'] = merged['LISA_clus'].map(cluster_labels)

    fig = px.choropleth(
        merged,
        geojson=merged.geometry,
        locations=merged.index,
        color="LISA_clus",
        category_orders={"LISA_show": [1, 4, 2, 3]},
        color_discrete_map={
            "High-High": "red",
            "Low-High": "lightblue",
            "Low-Low": "blue",
            "High-Low": "orange"
        },
        title="LISA Cluster Map"
    )

    fig.update_geos(fitbounds="locations", visible=False)
    fig.update_layout(margin=dict(l=0, r=0, t=40, b=0))

    st.plotly_chart(fig, use_container_width=True)