Disusun Oleh
- Nayli Kurnia Ilahi (23031030045)
- Nisrina Aisyah (23031030041)
1. Library
packages <- c(
"sf", "spdep", "MASS", "car", "lmtest",
"dplyr", "ggplot2", "readxl", "knitr",
"kableExtra", "mgwnbr"
)
for (p in packages) {
if (!requireNamespace(p, quietly = TRUE)) {
install.packages(p)
}
library(p, character.only = TRUE)
}
## Linking to GEOS 3.14.1, GDAL 3.12.1, PROJ 9.7.1; sf_use_s2() is TRUE
## Loading required package: spData
## To access larger datasets in this package, install the spDataLarge
## package with: `install.packages('spDataLarge',
## repos='https://nowosad.github.io/drat/', type='source')`
## Loading required package: carData
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
## Attaching package: 'dplyr'
## The following object is masked from 'package:car':
##
## recode
## The following object is masked from 'package:MASS':
##
## select
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
##
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
##
## group_rows
## Spherical geometry (s2) switched off
fungsi bantu
bersih_nama <- function(x) {
x <- as.character(x)
x <- iconv(x, to = "ASCII//TRANSLIT")
x <- tolower(trimws(x))
x <- gsub("\\s+", " ", x)
return(x)
}
ubah_numeric <- function(x) {
x <- as.character(x)
x <- gsub("\\.", "", x) # menghapus titik ribuan jika ada
x <- gsub(",", ".", x) # mengubah koma desimal menjadi titik
x <- trimws(x)
as.numeric(x)
}
ambil_aic_mgwnbr <- function(x) {
if (is.null(x)) return(NA_real_)
# kalau output berupa numeric vector
if (is.numeric(x) && !is.null(names(x))) {
idx <- grep("aic", names(x), ignore.case = TRUE)
if (length(idx) > 0) return(as.numeric(x[idx[1]]))
}
# kalau output berupa data frame / matrix
x_df <- tryCatch(as.data.frame(x), error = function(e) NULL)
if (is.null(x_df)) return(NA_real_)
kolom_aic <- grep("aic", names(x_df), ignore.case = TRUE, value = TRUE)
if (length(kolom_aic) > 0) {
return(as.numeric(x_df[1, kolom_aic[1]]))
}
baris_aic <- grep("aic", rownames(x_df), ignore.case = TRUE)
if (length(baris_aic) > 0) {
return(as.numeric(x_df[baris_aic[1], 1]))
}
return(NA_real_)
}
4. Load data
shp <- st_read(shp_path, quiet = TRUE)
if (grepl("\\.csv$", data_path, ignore.case = TRUE)) {
data_raw <- read.csv2(data_path, stringsAsFactors = FALSE, check.names = FALSE)
} else if (grepl("\\.xlsx?$", data_path, ignore.case = TRUE)) {
data_raw <- readxl::read_excel(data_path)
} else {
stop("Format data harus .csv, .xls, atau .xlsx")
}
names(data_raw) <- trimws(names(data_raw))
names(shp) <- trimws(names(shp))
cat("Jumlah wilayah shapefile :", nrow(shp), "\n")
## Jumlah wilayah shapefile : 35
cat("Jumlah baris data :", nrow(data_raw), "\n")
## Jumlah baris data : 35
cat("Kolom data :", paste(names(data_raw), collapse = ", "), "\n")
## Kolom data : Provinsi, Y, X1, X2, X3, X4
if (!(kolom_wilayah_data %in% names(data_raw))) {
stop("Kolom wilayah pada data tidak ditemukan.")
}
if (!(kolom_wilayah_shp %in% names(shp))) {
stop("Kolom wilayah pada shapefile tidak ditemukan.")
}
5. Join data dengan shapefile
data_raw$join_key <- bersih_nama(data_raw[[kolom_wilayah_data]])
shp$join_key <- bersih_nama(shp[[kolom_wilayah_shp]])
cek_tidak_cocok <- setdiff(data_raw$join_key, shp$join_key)
if (length(cek_tidak_cocok) > 0) {
cat("\nNama wilayah di data yang tidak cocok dengan shapefile:\n")
print(cek_tidak_cocok)
}
data_sf <- shp %>%
left_join(data_raw, by = "join_key")
cat("\nHasil join:", nrow(data_sf), "wilayah\n")
##
## Hasil join: 35 wilayah
6. Cleaning variabel
variabel_model <- c("Y", "X1", "X2", "X3", "X4")
for (v in variabel_model) {
if (!(v %in% names(data_sf))) {
stop(paste("Variabel", v, "tidak ditemukan pada data."))
}
}
data_sf <- data_sf %>%
mutate(
Y = ubah_numeric(Y),
X1 = ubah_numeric(X1),
X2 = ubah_numeric(X2),
X3 = ubah_numeric(X3),
X4 = ubah_numeric(X4),
)
# Y harus berupa data cacah
data_sf$Y_count <- as.integer(round(data_sf$Y))
# Cek missing value
cat("\nMissing value sebelum dibersihkan:\n")
##
## Missing value sebelum dibersihkan:
print(colSums(is.na(st_drop_geometry(data_sf)[, c("Y_count", "X1", "X2", "X3", "X4")])))
## Y_count X1 X2 X3 X4
## 0 0 0 0 0
# Pakai hanya data lengkap
cc <- complete.cases(st_drop_geometry(data_sf)[, c("Y_count", "X1", "X2", "X3", "X4")])
data_sf <- data_sf[cc, ]
if (any(data_sf$Y_count < 0, na.rm = TRUE)) {
stop("Y_count mengandung nilai negatif. Data count tidak boleh negatif.")
}
cat("\nJumlah data setelah cleaning:", nrow(data_sf), "\n")
##
## Jumlah data setelah cleaning: 35
7. Koordinat centroid
if (is.na(st_crs(data_sf))) {
stop("CRS shapefile tidak terbaca. Tetapkan CRS dulu sebelum analisis spasial.")
}
data_sf <- st_make_valid(data_sf)
data_sf <- st_transform(data_sf, 4326)
centroid_sf <- suppressWarnings(st_point_on_surface(data_sf))
coords <- st_coordinates(centroid_sf)
data_sf$long <- coords[, 1]
data_sf$lat <- coords[, 2]
# Data tanpa geometri untuk model
df_model <- data_sf %>%
st_drop_geometry() %>%
mutate(
wilayah = .data[[kolom_wilayah_shp]]
)
9. Statistik Deskriptif
df_desc <- df_model[, c("Y_count", x_vars)]
desc_tbl <- data.frame(
Variabel = names(df_desc),
N = sapply(df_desc, function(x) sum(!is.na(x))),
Min = sapply(df_desc, min, na.rm = TRUE),
Mean = sapply(df_desc, mean, na.rm = TRUE),
Median = sapply(df_desc, median, na.rm = TRUE),
Max = sapply(df_desc, max, na.rm = TRUE),
SD = sapply(df_desc, sd, na.rm = TRUE),
row.names = NULL
)
kable(desc_tbl, caption = "Statistik Deskriptif Variabel Penelitian", digits = 4) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Statistik Deskriptif Variabel Penelitian
|
Variabel
|
N
|
Min
|
Mean
|
Median
|
Max
|
SD
|
|
Y_count
|
35
|
8
|
257.7143
|
197
|
1066
|
217.1128
|
|
X1
|
35
|
3
|
9.0571
|
8
|
25
|
4.6838
|
|
X2
|
35
|
0
|
24.7714
|
15
|
86
|
22.2249
|
|
X3
|
35
|
467
|
2098.2571
|
1196
|
11324
|
2414.0985
|
|
X4
|
35
|
11
|
803.7714
|
824
|
1415
|
421.7383
|
10. Multikolinearitas
model_vif <- lm(form_model, data = df_model)
vif_val <- car::vif(model_vif)
vif_tbl <- data.frame(
Variabel = names(vif_val),
VIF = round(vif_val, 4),
Keputusan = ifelse(vif_val > 10, "Ada multikolinearitas", "Tidak ada multikolinearitas"),
row.names = NULL
)
kable(vif_tbl, caption = "Nilai VIF Prediktor") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Nilai VIF Prediktor
|
Variabel
|
VIF
|
Keputusan
|
|
X1
|
1.2106
|
Tidak ada multikolinearitas
|
|
X2
|
1.2374
|
Tidak ada multikolinearitas
|
|
X3
|
1.2447
|
Tidak ada multikolinearitas
|
|
X4
|
1.0805
|
Tidak ada multikolinearitas
|
11. Model Regresi Poison
model_poisson <- glm(
form_model,
family = poisson(link = "log"),
data = df_model
)
cat("\n==============================\n")
##
## ==============================
## MODEL POISSON
cat("==============================\n")
## ==============================
print(summary(model_poisson))
##
## Call:
## glm(formula = form_model, family = poisson(link = "log"), data = df_model)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 4.638e+00 3.981e-02 116.508 <2e-16 ***
## X1 8.392e-02 2.339e-03 35.876 <2e-16 ***
## X2 6.442e-03 4.798e-04 13.427 <2e-16 ***
## X3 -1.759e-04 8.280e-06 -21.246 <2e-16 ***
## X4 2.468e-04 2.752e-05 8.967 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for poisson family taken to be 1)
##
## Null deviance: 5558.4 on 34 degrees of freedom
## Residual deviance: 2946.5 on 30 degrees of freedom
## AIC: 3200.9
##
## Number of Fisher Scoring iterations: 5
12. Uji overdispersi
dev_pois <- deviance(model_poisson)
df_pois <- df.residual(model_poisson)
rasio_dev <- dev_pois / df_pois
rasio_pearson <- sum(residuals(model_poisson, type = "pearson")^2) / df_pois
cat("\n==============================\n")
##
## ==============================
cat("UJI OVERDISPERSI\n")
## UJI OVERDISPERSI
cat("==============================\n")
## ==============================
cat("Deviance Poisson :", round(dev_pois, 4), "\n")
## Deviance Poisson : 2946.503
cat("df residual :", df_pois, "\n")
## df residual : 30
cat("Rasio Deviance/df :", round(rasio_dev, 4), "\n")
## Rasio Deviance/df : 98.2168
cat("Rasio Pearson ChiSq/df :", round(rasio_pearson, 4), "\n")
## Rasio Pearson ChiSq/df : 99.7037
if (rasio_dev > 1 || rasio_pearson > 1) {
cat("Keputusan: Terjadi overdispersi.\n")
cat("Artinya model Negative Binomial lebih sesuai dibanding Poisson.\n")
} else {
cat("Keputusan: Tidak terindikasi overdispersi.\n")
}
## Keputusan: Terjadi overdispersi.
## Artinya model Negative Binomial lebih sesuai dibanding Poisson.
13. Model Negative Binomial global
model_nb <- MASS::glm.nb(
form_model,
data = df_model
)
cat("\n==============================\n")
##
## ==============================
cat("MODEL NEGATIVE BINOMIAL GLOBAL\n")
## MODEL NEGATIVE BINOMIAL GLOBAL
cat("==============================\n")
## ==============================
##
## Call:
## MASS::glm.nb(formula = form_model, data = df_model, init.theta = 2.322325954,
## link = log)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 4.331e+00 3.699e-01 11.709 < 2e-16 ***
## X1 9.316e-02 2.659e-02 3.503 0.000459 ***
## X2 9.399e-03 5.656e-03 1.662 0.096553 .
## X3 -1.364e-04 5.265e-05 -2.590 0.009587 **
## X4 3.259e-04 2.792e-04 1.168 0.242993
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for Negative Binomial(2.3223) family taken to be 1)
##
## Null deviance: 64.770 on 34 degrees of freedom
## Residual deviance: 37.712 on 30 degrees of freedom
## AIC: 448.09
##
## Number of Fisher Scoring iterations: 1
##
##
## Theta: 2.322
## Std. Err.: 0.536
##
## 2 x log-likelihood: -436.087
theta_nb <- model_nb$theta
alpha_nb <- 1 / theta_nb
cat("\nTheta NB dari glm.nb :", round(theta_nb, 6), "\n")
##
## Theta NB dari glm.nb : 2.322326
cat("Alpha NB = 1/theta :", round(alpha_nb, 6), "\n")
## Alpha NB = 1/theta : 0.430603
cat("AIC Poisson :", round(AIC(model_poisson), 4), "\n")
## AIC Poisson : 3200.923
cat("AIC NB Global :", round(AIC(model_nb), 4), "\n")
## AIC NB Global : 448.0866
14. Uji simultan model NB
model_nb_null <- MASS::glm.nb(Y_count ~ 1, data = df_model)
D_nb <- as.numeric(2 * (logLik(model_nb) - logLik(model_nb_null)))
df_nb <- length(coef(model_nb)) - 1
chi_nb <- qchisq(0.95, df_nb)
p_nb_simultan <- pchisq(D_nb, df = df_nb, lower.tail = FALSE)
cat("\n==============================\n")
##
## ==============================
cat("UJI SIMULTAN MODEL NB\n")
## UJI SIMULTAN MODEL NB
cat("==============================\n")
## ==============================
cat("D hitung :", round(D_nb, 4), "\n")
## D hitung : 20.6441
## df : 4
cat("Chi-square 0.95 :", round(chi_nb, 4), "\n")
## Chi-square 0.95 : 9.4877
cat("p-value :", round(p_nb_simultan, 6), "\n")
## p-value : 0.000372
if (p_nb_simultan < 0.05) {
cat("Keputusan: Tolak H0. Minimal ada satu prediktor berpengaruh.\n")
} else {
cat("Keputusan: Gagal tolak H0.\n")
}
## Keputusan: Tolak H0. Minimal ada satu prediktor berpengaruh.
15. Uji parsial model NB
coef_nb <- summary(model_nb)$coefficients
parsial_nb <- data.frame(
Variabel = rownames(coef_nb),
Koefisien = round(coef_nb[, 1], 6),
SE = round(coef_nb[, 2], 6),
Z_hitung = round(coef_nb[, 3], 6),
P_value = round(coef_nb[, 4], 6),
Keputusan = ifelse(coef_nb[, 4] < 0.05, "Signifikan", "Tidak signifikan"),
row.names = NULL
)
kable(parsial_nb, caption = "Uji Parsial Model Negative Binomial Global") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Uji Parsial Model Negative Binomial Global
|
Variabel
|
Koefisien
|
SE
|
Z_hitung
|
P_value
|
Keputusan
|
|
(Intercept)
|
4.331190
|
0.369898
|
11.709134
|
0.000000
|
Signifikan
|
|
X1
|
0.093158
|
0.026591
|
3.503386
|
0.000459
|
Signifikan
|
|
X2
|
0.009399
|
0.005656
|
1.661799
|
0.096553
|
Tidak signifikan
|
|
X3
|
-0.000136
|
0.000053
|
-2.590394
|
0.009587
|
Signifikan
|
|
X4
|
0.000326
|
0.000279
|
1.167539
|
0.242993
|
Tidak signifikan
|
16. Matriks ketetanggaan dan Moran’s I residual NB
nb_poly <- spdep::poly2nb(data_sf, queen = TRUE)
## although coordinates are longitude/latitude, st_intersects assumes that they
## are planar
lw_poly <- spdep::nb2listw(nb_poly, style = "W", zero.policy = TRUE)
res_nb <- residuals(model_nb, type = "pearson")
moran_nb <- spdep::moran.test(
res_nb,
lw_poly,
zero.policy = TRUE
)
cat("\n==============================\n")
##
## ==============================
cat("MORAN'S I RESIDUAL NB\n")
## MORAN'S I RESIDUAL NB
cat("==============================\n")
## ==============================
##
## Moran I test under randomisation
##
## data: res_nb
## weights: lw_poly
##
## Moran I statistic standard deviate = 0.222, p-value = 0.4122
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic Expectation Variance
## -0.003913935 -0.029411765 0.013192128
p_moran <- moran_nb$p.value
I_moran <- moran_nb$estimate[["Moran I statistic"]]
cat("\nMoran's I :", round(I_moran, 6), "\n")
##
## Moran's I : -0.003914
cat("p-value :", round(p_moran, 6), "\n")
## p-value : 0.412158
if (p_moran < 0.05) {
cat("Keputusan: Ada autokorelasi spasial pada residual.\n")
cat("Artinya analisis GWNBR layak dilanjutkan.\n")
} else {
cat("Keputusan: Tidak terdapat autokorelasi spasial yang signifikan.\n")
cat("Catatan: GWNBR masih bisa dicoba, tetapi alasan spasialnya lebih lemah.\n")
}
## Keputusan: Tidak terdapat autokorelasi spasial yang signifikan.
## Catatan: GWNBR masih bisa dicoba, tetapi alasan spasialnya lebih lemah.
17. Uji heterogenitas / Breusch-Pagan
bp_test <- lmtest::bptest(model_vif)
cat("\n==============================\n")
##
## ==============================
cat("UJI HETEROGENITAS BREUSCH-PAGAN\n")
## UJI HETEROGENITAS BREUSCH-PAGAN
cat("==============================\n")
## ==============================
##
## studentized Breusch-Pagan test
##
## data: model_vif
## BP = 11.641, df = 4, p-value = 0.02023
if (bp_test$p.value < 0.05) {
cat("Keputusan: Tolak H0. Ada heterogenitas.\n")
cat("Artinya parameter lokal GWNBR layak dipertimbangkan.\n")
} else {
cat("Keputusan: Gagal tolak H0. Heterogenitas belum signifikan.\n")
}
## Keputusan: Tolak H0. Ada heterogenitas.
## Artinya parameter lokal GWNBR layak dipertimbangkan.
18. Model GWNBR menggunakan paket mgwnbr
options(warn = -1)
model_gwnbr <- mgwnbr::mgwnbr(
data = df_model,
formula = form_model,
long = "long",
lat = "lat",
band_method = "adaptive_bsq",
band_criterion = "aic",
distribution = "negbin",
globalmin = TRUE,
multiscale = FALSE,
distancekm = TRUE,
id = "wilayah",
max_int = 50
)
## NOTE: The denominator degrees of freedom for the t tests is 29.
cat("\n==============================\n")
##
## ==============================
## MODEL GWNBR
cat("==============================\n")
## ==============================
## General Bandwidth:
## [1] 8
##
## Fitted Values:
## wt Y yhat res
## Cilacap 1 401 548.770403 -147.77040302
## Banyumas 1 1066 1065.715011 0.28498931
## Purbalingga 1 178 190.482695 -12.48269526
## Banjarnegara 1 308 309.569967 -1.56996707
## Kebumen 1 130 130.525113 -0.52511262
## Purworejo 1 336 268.152394 67.84760646
## Wonosobo 1 268 295.509858 -27.50985766
## Magelang 1 157 160.197348 -3.19734811
## Boyolali 1 342 342.164923 -0.16492274
## Klaten 1 505 504.958073 0.04192670
## Sukoharjo 1 251 293.554213 -42.55421262
## Wonogiri 1 197 219.560456 -22.56045566
## Karanganyar 1 362 318.228266 43.77173352
## Sragen 1 249 272.869543 -23.86954325
## Grobogan 1 485 484.279439 0.72056084
## Blora 1 133 143.117441 -10.11744097
## Rembang 1 81 80.297453 0.70254750
## Pati 1 330 356.129687 -26.12968667
## Kudus 1 206 191.199192 14.80080802
## Jepara 1 117 121.677627 -4.67762744
## Demak 1 420 422.662932 -2.66293194
## Semarang 1 56 53.595205 2.40479472
## Temanggung 1 27 29.343752 -2.34375191
## Kendal 1 372 368.314895 3.68510477
## Batang 1 83 86.125262 -3.12526157
## Pekalongan 1 112 111.480197 0.51980275
## Pemalang 1 117 132.522547 -15.52254668
## Tegal 1 629 628.989018 0.01098207
## Brebes 1 615 559.251827 55.74817342
## Kota Magelang 1 9 8.763287 0.23671263
## Kota Surakarta 1 114 112.697072 1.30292777
## Kota Salatiga 1 8 9.526749 -1.52674921
## Kota Semarang 1 131 131.015838 -0.01583776
## Kota Pekalongan 1 161 160.561861 0.43813927
## Kota Tegal 1 64 62.989553 1.01044727
##
## Goodness of Fit Measures:
## deviance full_Log_likelihood pctdev adjpctdev
## 7.8384030 -146.7663260 0.9977697 1.0459347
## AIC AICc
## 366.8343756 -674.2885691
##
## Effective Number of Parameters:
## Intercept X1 X2 X3 X4 MGWR GWR alpha
## 30.542385 30.542385 30.542385 30.542385 30.542385 30.542385 30.542385 6.108477
##
## Parameter Estimates:
## Intercept X1 X2 X3
## Cilacap 5.0392371 0.159633223 -0.001123033 -7.282204e-05
## Banyumas 3.5423022 0.150309181 0.004900755 9.575498e-04
## Purbalingga 11.7868536 0.180409054 -0.078084262 -2.235446e-03
## Banjarnegara -0.9803372 -0.455808116 0.077442670 2.410718e-03
## Kebumen 8.3759588 0.202960678 -0.076067795 -2.223626e-03
## Purworejo 4.1840615 0.266732242 -0.061641123 -6.796266e-04
## Wonosobo 1.9367883 0.587791140 -0.129507849 -7.742867e-04
## Magelang 2.4591043 0.525616370 -0.112876238 -7.582885e-04
## Boyolali 1.1425618 0.398952753 0.021883742 -2.618487e-04
## Klaten 2.4619184 0.007827100 0.104158106 -6.068827e-05
## Sukoharjo 6.6321243 0.056939255 -0.023391650 -1.566799e-04
## Wonogiri 6.9519833 0.093036391 -0.042148485 -1.956519e-04
## Karanganyar 6.6490205 0.064042264 -0.030704010 -1.711696e-04
## Sragen 6.5022300 -0.004410891 0.008634883 -1.016985e-04
## Grobogan 9.2326632 -0.081946766 0.004066531 -1.276418e-03
## Blora 4.1028186 0.123586949 0.007185064 5.016516e-04
## Rembang 2.8255731 0.152676223 0.011596029 2.408043e-04
## Pati 3.3579048 0.095301268 0.015528369 1.846186e-04
## Kudus 3.7049352 0.045676028 0.008036636 -2.786412e-06
## Jepara 4.1376423 0.026561934 0.012210441 -7.694410e-05
## Demak 1.6737248 0.048327830 -0.012087075 5.123135e-04
## Semarang 3.6905182 0.280755564 -0.061387648 -6.720440e-04
## Temanggung -4.3691169 1.462402654 -0.012515665 -8.769185e-04
## Kendal 3.2664084 0.005822745 0.042239443 -8.812103e-05
## Batang -2.9125057 -1.204160417 0.263549370 1.090645e-03
## Pekalongan 1.0079684 -0.291716562 0.070011774 3.896996e-04
## Pemalang 8.9760570 0.185886409 -0.084799927 -2.837082e-04
## Tegal 5.8028712 0.166671661 0.011915663 -1.316734e-04
## Brebes 5.4708947 0.170305764 0.007269430 -1.091629e-04
## Kota Magelang 2.4426562 0.530650009 -0.113988042 -7.626556e-04
## Kota Surakarta 6.1875406 0.036750034 -0.005701447 -1.312591e-04
## Kota Salatiga 3.6915465 0.097263162 0.034334610 -5.447539e-04
## Kota Semarang 3.5811901 0.080211122 0.035993397 -4.892770e-04
## Kota Pekalongan 1.2728294 -0.214251629 0.079220583 3.084919e-04
## Kota Tegal 4.9379924 0.262944080 0.004084498 -3.270503e-05
## X4 alpha
## Cilacap -7.390704e-04 0.0636708743
## Banyumas -5.862376e-04 0.0000010000
## Purbalingga -3.153040e-03 0.0782278434
## Banjarnegara 4.213088e-03 0.0000010000
## Kebumen -6.191258e-04 0.0057897825
## Purworejo 1.005169e-03 0.1312668996
## Wonosobo 2.263604e-03 0.0293529739
## Magelang 1.853832e-03 0.0000010000
## Boyolali -4.635290e-04 0.0000010000
## Klaten 2.865157e-03 0.0030533428
## Sukoharjo -1.239388e-03 0.0193597718
## Wonogiri -1.727705e-03 0.0198953604
## Karanganyar -1.149289e-03 0.0203977181
## Sragen -7.875857e-04 0.0152457891
## Grobogan -1.302515e-03 0.0003237762
## Blora -4.713007e-04 0.0471078196
## Rembang 5.032652e-04 0.0000010000
## Pati 3.635722e-04 0.0049462703
## Kudus 1.291331e-03 0.0000010000
## Jepara 7.764538e-04 0.0060046036
## Demak 4.102519e-03 0.0000010000
## Semarang 9.739057e-05 0.0318618066
## Temanggung 3.735220e-03 0.0000010000
## Kendal 3.449548e-04 0.1352114491
## Batang 7.637987e-03 0.0082736969
## Pekalongan 3.697047e-03 0.0000010000
## Pemalang -3.142732e-03 0.0387082044
## Tegal -1.741547e-03 0.0178578012
## Brebes -1.421583e-03 0.0535844776
## Kota Magelang 1.856547e-03 0.0000010000
## Kota Surakarta -7.373223e-04 0.0260810633
## Kota Salatiga 1.394895e-03 0.0915100219
## Kota Semarang -4.545999e-04 0.0000010000
## Kota Pekalongan 2.879960e-03 0.0330226218
## Kota Tegal -1.888519e-03 0.0000010000
##
## Alpha Levels for Parameter Significance Tests:
## Intercept X1 X2 X3 X4 MGWR
## 0.008185346 0.008185346 0.008185346 0.008185346 0.008185346 0.008185346
## GWR alpha
## 0.008185346 0.008185346
##
## Critical Values for Parameter Significance Tests:
## Intercept X1 X2 X3 X4 MGWR GWR alpha
## 4.53 4.53 4.53 4.53 4.53 4.53 4.53 4.53
##
## Standard Errors for Parameter Estimates:
## Intercept X1 X2 X3 X4
## Cilacap 0.5312326 0.032290354 0.007157249 7.929872e-05 4.235313e-04
## Banyumas 0.2329360 0.006209268 0.001376785 9.454190e-05 9.747809e-05
## Purbalingga 2.0882921 0.033872887 0.015426323 8.805393e-04 7.558922e-04
## Banjarnegara 2.1056137 0.106089659 0.023748084 7.678188e-04 8.030052e-04
## Kebumen 1.0042269 0.018416335 0.006292032 3.432885e-04 4.921227e-04
## Purworejo 2.5766511 0.218530767 0.058013572 1.499437e-04 7.886755e-04
## Wonosobo 0.9396100 0.077963644 0.020658689 8.409440e-05 3.081474e-04
## Magelang 0.4575989 0.038179217 0.009459021 6.226593e-05 1.224427e-04
## Boyolali 0.3770084 0.034399131 0.004715689 1.868503e-05 1.286888e-04
## Klaten 0.5039468 0.023236682 0.010932055 2.074555e-05 3.644154e-04
## Sukoharjo 0.5219908 0.033269584 0.011596547 3.444235e-05 3.074185e-04
## Wonogiri 0.6689032 0.039778107 0.015488458 4.192212e-05 4.039296e-04
## Karanganyar 0.5713612 0.035716760 0.013317448 3.782250e-05 3.195217e-04
## Sragen 0.4770897 0.028150551 0.002919103 2.759336e-05 4.770471e-04
## Grobogan 0.6703231 0.033913968 0.001881376 2.417717e-04 3.531902e-04
## Blora 1.2809294 0.043623905 0.005046148 4.467619e-04 8.218481e-04
## Rembang 0.4035461 0.026889028 0.002741458 1.016062e-04 2.513021e-04
## Pati 0.4620105 0.021693124 0.001896264 1.414881e-04 2.993008e-04
## Kudus 0.2857620 0.007671253 0.002107133 6.171139e-05 2.703069e-04
## Jepara 0.4099190 0.012713067 0.002872528 9.245179e-05 3.832488e-04
## Demak 1.8213676 0.009461351 0.012898480 3.849635e-04 1.853896e-03
## Semarang 0.6173247 0.030706760 0.014439102 8.543316e-05 3.247741e-04
## Temanggung 1.2245382 0.123586062 0.002926113 6.967521e-05 2.928618e-04
## Kendal 1.0076502 0.064882707 0.010617254 3.130590e-04 3.999601e-04
## Batang 1.9477817 0.178425893 0.026806064 1.355009e-04 6.700751e-04
## Pekalongan 0.5454190 0.030679577 0.013264913 3.891421e-05 3.834078e-04
## Pemalang 0.8811081 0.044709293 0.022981098 6.024742e-05 6.281075e-04
## Tegal 0.3016100 0.016457263 0.004177296 4.359550e-05 2.483138e-04
## Brebes 0.4715367 0.029219050 0.006445536 6.599982e-05 3.669214e-04
## Kota Magelang 0.4576011 0.038238159 0.009461626 6.156373e-05 1.228595e-04
## Kota Surakarta 0.6394957 0.038660053 0.014163431 3.858359e-05 3.938149e-04
## Kota Salatiga 1.1188463 0.057524277 0.024031871 9.725101e-05 5.626867e-04
## Kota Semarang 0.3773033 0.024829451 0.002372228 1.214037e-04 1.357323e-04
## Kota Pekalongan 1.3449211 0.087961965 0.027434232 9.842689e-05 9.681721e-04
## Kota Tegal 0.1978617 0.016170638 0.003386150 1.958337e-05 1.113724e-04
## alpha
## Cilacap 5.264082e-02
## Banyumas 2.830441e-05
## Purbalingga 6.694274e-02
## Banjarnegara 4.133834e-05
## Kebumen 7.791436e-03
## Purworejo 1.083395e-01
## Wonosobo 3.913585e-02
## Magelang 8.345049e-05
## Boyolali 4.727340e-05
## Klaten 4.335494e-03
## Sukoharjo 1.564508e-02
## Wonogiri 1.752868e-02
## Karanganyar 1.806303e-02
## Sragen 1.444847e-02
## Grobogan 2.282221e-03
## Blora 4.514423e-02
## Rembang 4.749461e-05
## Pati 6.606592e-03
## Kudus 4.683118e-05
## Jepara 7.980224e-03
## Demak 4.023561e-05
## Semarang 4.999973e-02
## Temanggung 9.569966e-05
## Kendal 1.276061e-01
## Batang 1.229117e-02
## Pekalongan 6.995792e-05
## Pemalang 3.714384e-02
## Tegal 1.955867e-02
## Brebes 4.092498e-02
## Kota Magelang 1.322525e-04
## Kota Surakarta 2.335085e-02
## Kota Salatiga 9.729921e-02
## Kota Semarang 4.519957e-05
## Kota Pekalongan 3.103441e-02
## Kota Tegal 4.356338e-05
##
## Global Parameter Estimates:
## Par. Est. Std Error t Value Pr > |t|
## Intercept 4.3311902301 3.992715e-01 10.847731 1.009548e-11
## X1 0.0931576112 2.817338e-02 3.306583 2.523655e-03
## X2 0.0093994014 5.452890e-03 1.723747 9.540075e-02
## X3 -0.0001363947 4.983132e-05 -2.737128 1.047474e-02
## X4 0.0003259440 2.855230e-04 1.141568 2.629725e-01
## alpha 0.4306027746 9.937915e-02 4.332929 1.609572e-04
##
## Denominator Degrees of Freedom for the T Tests:
## [1] 29
##
## Goodness of Fit Statistics for the Global Model:
## deviance full_Log_likelihood pctdevg adjpctdevg
## 37.7122798 -315.7223367 0.4177487 0.3401152
## AIC AICc
## 643.4446734 646.4446734
cat("\nRingkasan model GWNBR:\n")
##
## Ringkasan model GWNBR:
print(summary(model_gwnbr))
## Model Summary:
##
## General Bandwidth:
## [1] 8
##
## Effective Number of Parameters and T Test Information:
## Intercept X1 X2 X3
## ENP 30.542384854 30.542384854 30.542384854 30.542384854
## alpha_level_5_pct 0.008185346 0.008185346 0.008185346 0.008185346
## t_critical 4.530000000 4.530000000 4.530000000 4.530000000
## X4 MGWR GWR alpha
## ENP 30.542384854 30.542384854 30.542384854 6.108476971
## alpha_level_5_pct 0.008185346 0.008185346 0.008185346 0.008185346
## t_critical 4.530000000 4.530000000 4.530000000 4.530000000
##
## Five Number Summary for Parameter Estimates:
## Intercept X1 X2 X3 X4
## Min -4.369117 -1.20416042 -0.129507849 -2.235446e-03 -3.153040e-03
## 1Q 2.450880 0.03165598 -0.036426248 -6.083990e-04 -9.684372e-04
## Median 3.691547 0.09726316 0.004900755 -1.312591e-04 9.739057e-05
## 3Q 5.995206 0.19442354 0.018706056 9.091611e-05 1.855189e-03
## Max 11.786854 1.46240265 0.263549370 2.410718e-03 7.637987e-03
## alpha
## Min 0.000001000
## 1Q 0.000001000
## Median 0.008273697
## 3Q 0.032442214
## Max 0.135211449
##
## Five Number Summary for Standard Errors:
## Intercept X1 X2 X3 X4 alpha
## Min 0.1978617 0.006209268 0.001376785 1.868503e-05 9.747809e-05 2.830441e-05
## 1Q 0.4576000 0.024033067 0.003156131 4.275881e-05 2.815843e-04 7.670421e-05
## Median 0.5713612 0.033872887 0.009461626 8.409440e-05 3.669214e-04 1.229117e-02
## 3Q 1.0632483 0.044166599 0.014932712 1.384945e-04 5.274047e-04 3.813984e-02
## Max 2.5766511 0.218530767 0.058013572 8.805393e-04 1.853896e-03 1.276061e-01
##
## Deviance: 7.8384, Full Log-Likelihood: -146.7663
## AIC: 366.8344, AICc: -674.2886
cat("\nNama komponen output mgwnbr:\n")
##
## Nama komponen output mgwnbr:
print(names(model_gwnbr))
## [1] "general_bandwidth" "fitted_values" "measures"
## [4] "ENP" "mgwr_param_estimates" "alpha_level_5_pct"
## [7] "t_critical" "mgwr_se" "global_param_estimates"
## [10] "t_test_dfs" "global_measures"
19. Goodness of fit GWNBR
cat("\n==============================\n")
##
## ==============================
cat("GOODNESS OF FIT GWNBR\n")
## GOODNESS OF FIT GWNBR
cat("==============================\n")
## ==============================
if (!is.null(model_gwnbr$general_bandwidth)) {
cat("\nBandwidth umum:\n")
print(model_gwnbr$general_bandwidth)
}
##
## Bandwidth umum:
## [1] 8
if (!is.null(model_gwnbr$band)) {
cat("\nBandwidth:\n")
print(model_gwnbr$band)
}
if (!is.null(model_gwnbr$measures)) {
cat("\nMeasures GWNBR:\n")
print(model_gwnbr$measures)
}
##
## Measures GWNBR:
## deviance full_Log_likelihood pctdev adjpctdev
## 7.8384030 -146.7663260 0.9977697 1.0459347
## AIC AICc
## 366.8343756 -674.2885691
if (!is.null(model_gwnbr$global_measures)) {
cat("\nGlobal measures dari mgwnbr:\n")
print(model_gwnbr$global_measures)
}
##
## Global measures dari mgwnbr:
## deviance full_Log_likelihood pctdevg adjpctdevg
## 37.7122798 -315.7223367 0.4177487 0.3401152
## AIC AICc
## 643.4446734 646.4446734
20. Koefisien lokal GWNBR
if (!is.null(model_gwnbr$mgwr_param_estimates)) {
coef_lokal <- as.data.frame(model_gwnbr$mgwr_param_estimates)
coef_lokal$Wilayah <- df_model$wilayah
coef_lokal <- coef_lokal %>%
dplyr::select(Wilayah, everything())
kable(coef_lokal,
caption = "Koefisien Lokal GWNBR per Kabupaten/Kota",
digits = 6) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE) %>%
scroll_box(height = "400px")
} else {
cat("Komponen mgwr_param_estimates tidak ditemukan pada output mgwnbr.\n")
}
Koefisien Lokal GWNBR per Kabupaten/Kota
|
|
Wilayah
|
Intercept
|
X1
|
X2
|
X3
|
X4
|
alpha
|
|
Cilacap
|
Cilacap
|
5.039237
|
0.159633
|
-0.001123
|
-0.000073
|
-0.000739
|
0.063671
|
|
Banyumas
|
Banyumas
|
3.542302
|
0.150309
|
0.004901
|
0.000958
|
-0.000586
|
0.000001
|
|
Purbalingga
|
Purbalingga
|
11.786854
|
0.180409
|
-0.078084
|
-0.002235
|
-0.003153
|
0.078228
|
|
Banjarnegara
|
Banjarnegara
|
-0.980337
|
-0.455808
|
0.077443
|
0.002411
|
0.004213
|
0.000001
|
|
Kebumen
|
Kebumen
|
8.375959
|
0.202961
|
-0.076068
|
-0.002224
|
-0.000619
|
0.005790
|
|
Purworejo
|
Purworejo
|
4.184061
|
0.266732
|
-0.061641
|
-0.000680
|
0.001005
|
0.131267
|
|
Wonosobo
|
Wonosobo
|
1.936788
|
0.587791
|
-0.129508
|
-0.000774
|
0.002264
|
0.029353
|
|
Magelang
|
Magelang
|
2.459104
|
0.525616
|
-0.112876
|
-0.000758
|
0.001854
|
0.000001
|
|
Boyolali
|
Boyolali
|
1.142562
|
0.398953
|
0.021884
|
-0.000262
|
-0.000464
|
0.000001
|
|
Klaten
|
Klaten
|
2.461918
|
0.007827
|
0.104158
|
-0.000061
|
0.002865
|
0.003053
|
|
Sukoharjo
|
Sukoharjo
|
6.632124
|
0.056939
|
-0.023392
|
-0.000157
|
-0.001239
|
0.019360
|
|
Wonogiri
|
Wonogiri
|
6.951983
|
0.093036
|
-0.042148
|
-0.000196
|
-0.001728
|
0.019895
|
|
Karanganyar
|
Karanganyar
|
6.649021
|
0.064042
|
-0.030704
|
-0.000171
|
-0.001149
|
0.020398
|
|
Sragen
|
Sragen
|
6.502230
|
-0.004411
|
0.008635
|
-0.000102
|
-0.000788
|
0.015246
|
|
Grobogan
|
Grobogan
|
9.232663
|
-0.081947
|
0.004067
|
-0.001276
|
-0.001303
|
0.000324
|
|
Blora
|
Blora
|
4.102819
|
0.123587
|
0.007185
|
0.000502
|
-0.000471
|
0.047108
|
|
Rembang
|
Rembang
|
2.825573
|
0.152676
|
0.011596
|
0.000241
|
0.000503
|
0.000001
|
|
Pati
|
Pati
|
3.357905
|
0.095301
|
0.015528
|
0.000185
|
0.000364
|
0.004946
|
|
Kudus
|
Kudus
|
3.704935
|
0.045676
|
0.008037
|
-0.000003
|
0.001291
|
0.000001
|
|
Jepara
|
Jepara
|
4.137642
|
0.026562
|
0.012210
|
-0.000077
|
0.000776
|
0.006005
|
|
Demak
|
Demak
|
1.673725
|
0.048328
|
-0.012087
|
0.000512
|
0.004103
|
0.000001
|
|
Semarang
|
Semarang
|
3.690518
|
0.280756
|
-0.061388
|
-0.000672
|
0.000097
|
0.031862
|
|
Temanggung
|
Temanggung
|
-4.369117
|
1.462403
|
-0.012516
|
-0.000877
|
0.003735
|
0.000001
|
|
Kendal
|
Kendal
|
3.266408
|
0.005823
|
0.042239
|
-0.000088
|
0.000345
|
0.135211
|
|
Batang
|
Batang
|
-2.912506
|
-1.204160
|
0.263549
|
0.001091
|
0.007638
|
0.008274
|
|
Pekalongan
|
Pekalongan
|
1.007968
|
-0.291717
|
0.070012
|
0.000390
|
0.003697
|
0.000001
|
|
Pemalang
|
Pemalang
|
8.976057
|
0.185886
|
-0.084800
|
-0.000284
|
-0.003143
|
0.038708
|
|
Tegal
|
Tegal
|
5.802871
|
0.166672
|
0.011916
|
-0.000132
|
-0.001742
|
0.017858
|
|
Brebes
|
Brebes
|
5.470895
|
0.170306
|
0.007269
|
-0.000109
|
-0.001422
|
0.053584
|
|
Kota Magelang
|
Kota Magelang
|
2.442656
|
0.530650
|
-0.113988
|
-0.000763
|
0.001857
|
0.000001
|
|
Kota Surakarta
|
Kota Surakarta
|
6.187541
|
0.036750
|
-0.005701
|
-0.000131
|
-0.000737
|
0.026081
|
|
Kota Salatiga
|
Kota Salatiga
|
3.691547
|
0.097263
|
0.034335
|
-0.000545
|
0.001395
|
0.091510
|
|
Kota Semarang
|
Kota Semarang
|
3.581190
|
0.080211
|
0.035993
|
-0.000489
|
-0.000455
|
0.000001
|
|
Kota Pekalongan
|
Kota Pekalongan
|
1.272829
|
-0.214252
|
0.079221
|
0.000308
|
0.002880
|
0.033023
|
|
Kota Tegal
|
Kota Tegal
|
4.937992
|
0.262944
|
0.004084
|
-0.000033
|
-0.001889
|
0.000001
|
21. Standard error dan signifikansi lokal
if (!is.null(model_gwnbr$mgwr_param_estimates) &&
!is.null(model_gwnbr$mgwr_se)) {
beta_mat <- as.matrix(model_gwnbr$mgwr_param_estimates)
se_mat <- as.matrix(model_gwnbr$mgwr_se)
z_mat <- beta_mat / se_mat
p_mat <- 2 * (1 - pnorm(abs(z_mat)))
sig_mat <- p_mat < 0.05
sig_tbl <- as.data.frame(sig_mat)
sig_tbl$Wilayah <- df_model$wilayah
sig_tbl <- sig_tbl %>%
dplyr::select(Wilayah, everything())
kable(sig_tbl,
caption = "Signifikansi Lokal Parameter GWNBR, TRUE = Signifikan") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE) %>%
scroll_box(height = "400px")
# Pengelompokan wilayah berdasarkan variabel signifikan
kelompok_sig <- apply(sig_mat, 1, function(x) {
vars <- colnames(sig_mat)[x]
vars <- vars[!vars %in% c("(Intercept)", "Intercept")]
if (length(vars) == 0) {
return("Tidak ada variabel signifikan")
} else {
return(paste(vars, collapse = ", "))
}
})
data_sf$Kelompok_Signifikan <- kelompok_sig
kelompok_tbl <- data.frame(
Wilayah = df_model$wilayah,
Kelompok_Signifikan = kelompok_sig
)
kable(kelompok_tbl,
caption = "Kelompok Wilayah Berdasarkan Variabel Signifikan pada GWNBR") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
} else {
cat("Komponen mgwr_param_estimates atau mgwr_se tidak ditemukan.\n")
}
Kelompok Wilayah Berdasarkan Variabel Signifikan pada GWNBR
|
|
Wilayah
|
Kelompok_Signifikan
|
|
Cilacap
|
Cilacap
|
X1
|
|
Banyumas
|
Banyumas
|
X1, X2, X3, X4
|
|
Purbalingga
|
Purbalingga
|
X1, X2, X3, X4
|
|
Banjarnegara
|
Banjarnegara
|
X1, X2, X3, X4
|
|
Kebumen
|
Kebumen
|
X1, X2, X3
|
|
Purworejo
|
Purworejo
|
X3
|
|
Wonosobo
|
Wonosobo
|
X1, X2, X3, X4
|
|
Magelang
|
Magelang
|
X1, X2, X3, X4
|
|
Boyolali
|
Boyolali
|
X1, X2, X3, X4
|
|
Klaten
|
Klaten
|
X2, X3, X4
|
|
Sukoharjo
|
Sukoharjo
|
X2, X3, X4
|
|
Wonogiri
|
Wonogiri
|
X1, X2, X3, X4
|
|
Karanganyar
|
Karanganyar
|
X2, X3, X4
|
|
Sragen
|
Sragen
|
X2, X3
|
|
Grobogan
|
Grobogan
|
X1, X2, X3, X4
|
|
Blora
|
Blora
|
X1
|
|
Rembang
|
Rembang
|
X1, X2, X3, X4
|
|
Pati
|
Pati
|
X1, X2
|
|
Kudus
|
Kudus
|
X1, X2, X4
|
|
Jepara
|
Jepara
|
X1, X2, X4
|
|
Demak
|
Demak
|
X1, X4
|
|
Semarang
|
Semarang
|
X1, X2, X3
|
|
Temanggung
|
Temanggung
|
X1, X2, X3, X4
|
|
Kendal
|
Kendal
|
X2
|
|
Batang
|
Batang
|
X1, X2, X3, X4
|
|
Pekalongan
|
Pekalongan
|
X1, X2, X3, X4
|
|
Pemalang
|
Pemalang
|
X1, X2, X3, X4
|
|
Tegal
|
Tegal
|
X1, X2, X3, X4
|
|
Brebes
|
Brebes
|
X1, X4
|
|
Kota Magelang
|
Kota Magelang
|
X1, X2, X3, X4
|
|
Kota Surakarta
|
Kota Surakarta
|
X3
|
|
Kota Salatiga
|
Kota Salatiga
|
X3, X4
|
|
Kota Semarang
|
Kota Semarang
|
X1, X2, X3, X4
|
|
Kota Pekalongan
|
Kota Pekalongan
|
X1, X2, X3, X4
|
|
Kota Tegal
|
Kota Tegal
|
X1, X4
|
22. Perbandingan AIC Poisson, NB, dan GWNBR
AIC_pois <- AIC(model_poisson)
AIC_nb <- AIC(model_nb)
AIC_gwnbr <- ambil_aic_mgwnbr(model_gwnbr$measures)
perbandingan_aic <- data.frame(
Model = c("Regresi Poisson", "Regresi Negative Binomial Global", "GWNBR"),
AIC = c(round(AIC_pois, 4), round(AIC_nb, 4), round(AIC_gwnbr, 4))
)
kable(perbandingan_aic,
caption = "Perbandingan AIC Model") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Perbandingan AIC Model
|
Model
|
AIC
|
|
Regresi Poisson
|
3200.9233
|
|
Regresi Negative Binomial Global
|
448.0866
|
|
GWNBR
|
366.8344
|
cat("\n==============================\n")
##
## ==============================
cat("PERBANDINGAN AIC\n")
## PERBANDINGAN AIC
cat("==============================\n")
## ==============================
## Model AIC
## 1 Regresi Poisson 3200.9233
## 2 Regresi Negative Binomial Global 448.0866
## 3 GWNBR 366.8344
if (!is.na(AIC_gwnbr)) {
if (AIC_gwnbr < AIC_nb) {
cat("\nKesimpulan AIC: AIC GWNBR lebih kecil daripada AIC NB global.\n")
cat("Artinya GWNBR memberikan model yang lebih baik berdasarkan AIC.\n")
} else {
cat("\nKesimpulan AIC: AIC GWNBR belum lebih kecil daripada AIC NB global.\n")
cat("Coba cek kembali bandwidth, variabel, atau struktur spasial.\n")
}
} else {
cat("\nAIC GWNBR tidak berhasil diekstrak otomatis.\n")
cat("Lihat langsung pada output model_gwnbr$measures.\n")
}
##
## Kesimpulan AIC: AIC GWNBR lebih kecil daripada AIC NB global.
## Artinya GWNBR memberikan model yang lebih baik berdasarkan AIC.
25. Kesimpulan
cat("1. Model yang digunakan:\n")
## 1. Model yang digunakan:
cat(" Y_count ~ X1 + X2 + X3 + X4\n\n")
## Y_count ~ X1 + X2 + X3 + X4
cat("2. Overdispersi:\n")
## 2. Overdispersi:
cat(" Rasio Deviance/df =", round(rasio_dev, 4), "\n")
## Rasio Deviance/df = 98.2168
cat(" Rasio Pearson ChiSq/df =", round(rasio_pearson, 4), "\n")
## Rasio Pearson ChiSq/df = 99.7037
if (rasio_dev > 1 || rasio_pearson > 1) {
cat(" Kesimpulan: terjadi overdispersi, sehingga NB lebih sesuai daripada Poisson.\n\n")
} else {
cat(" Kesimpulan: overdispersi belum terlihat kuat.\n\n")
}
## Kesimpulan: terjadi overdispersi, sehingga NB lebih sesuai daripada Poisson.
cat("3. Model Negative Binomial global:\n")
## 3. Model Negative Binomial global:
cat(" AIC NB =", round(AIC_nb, 4), "\n")
## AIC NB = 448.0866
cat(" Theta =", round(theta_nb, 6), "\n")
## Theta = 2.322326
cat(" Alpha =", round(alpha_nb, 6), "\n\n")
## Alpha = 0.430603
cat("4. Moran's I residual NB:\n")
## 4. Moran's I residual NB:
cat(" Moran's I =", round(I_moran, 6), "\n")
## Moran's I = -0.003914
cat(" p-value =", round(p_moran, 6), "\n")
## p-value = 0.412158
if (p_moran < 0.05) {
cat(" Kesimpulan: terdapat autokorelasi spasial.\n\n")
} else {
cat(" Kesimpulan: autokorelasi spasial belum signifikan.\n\n")
}
## Kesimpulan: autokorelasi spasial belum signifikan.
cat("5. Heterogenitas Breusch-Pagan:\n")
## 5. Heterogenitas Breusch-Pagan:
cat(" BP statistic =", round(bp_test$statistic, 6), "\n")
## BP statistic = 11.64138
cat(" p-value =", round(bp_test$p.value, 6), "\n")
## p-value = 0.020227
if (bp_test$p.value < 0.05) {
cat(" Kesimpulan: terdapat heterogenitas.\n\n")
} else {
cat(" Kesimpulan: heterogenitas belum signifikan.\n\n")
}
## Kesimpulan: terdapat heterogenitas.
cat("6. Perbandingan AIC:\n")
## 6. Perbandingan AIC:
cat(" AIC Poisson =", round(AIC_pois, 4), "\n")
## AIC Poisson = 3200.923
cat(" AIC NB =", round(AIC_nb, 4), "\n")
## AIC NB = 448.0866
cat(" AIC GWNBR =", round(AIC_gwnbr, 4), "\n")
## AIC GWNBR = 366.8344
if (!is.na(AIC_gwnbr) && AIC_gwnbr < AIC_nb) {
cat(" Kesimpulan: GWNBR lebih baik daripada NB global berdasarkan AIC.\n")
} else if (!is.na(AIC_gwnbr) && AIC_gwnbr >= AIC_nb) {
cat(" Kesimpulan: GWNBR belum lebih baik daripada NB global berdasarkan AIC.\n")
} else {
cat(" Kesimpulan: AIC GWNBR perlu dilihat manual pada model_gwnbr$measures.\n")
}
## Kesimpulan: GWNBR lebih baik daripada NB global berdasarkan AIC.
VISUALISASI PETA
# ============================================================
# VISUALISASI PETA TEMATIK
# ============================================================
library(ggplot2)
library(sf)
library(dplyr)
library(ggrepel)
library(RColorBrewer)
library(scales)
# ── Label wilayah (centroid) ─────────────────────────────────
# Gunakan st_point_on_surface agar titik selalu jatuh di dalam polygon
centroids_label <- suppressWarnings(st_point_on_surface(st_geometry(data_sf)))
coords_label <- st_coordinates(centroids_label)
df_label <- data.frame(
wilayah = data_sf[[kolom_wilayah_shp]],
lx = coords_label[, 1],
ly = coords_label[, 2],
stringsAsFactors = FALSE
)
# ── Tema dasar peta ──────────────────────────────────────────
tema_peta <- theme_void(base_family = "sans") +
theme(
plot.title = element_text(face = "bold", size = 14, hjust = 0.5,
margin = margin(b = 8)),
plot.subtitle = element_text(size = 10, hjust = 0.5, color = "grey40",
margin = margin(b = 6)),
legend.position = "right",
legend.title = element_text(size = 9, face = "bold"),
legend.text = element_text(size = 8),
plot.margin = margin(10, 10, 10, 10),
panel.background = element_rect(fill = "#f0f4f8", color = NA),
plot.background = element_rect(fill = "white", color = NA)
)
# ────────────────────────────────────────────────────────────
# FUNGSI UTAMA: peta khoropleth satu variabel
# ────────────────────────────────────────────────────────────
buat_peta_khoropleth <- function(sf_data, var_col, judul, subjudul = "",
label_df, palet = "YlOrRd",
arah_palet = 1) {
sf_data$nilai_plot <- sf_data[[var_col]]
ggplot(sf_data) +
geom_sf(aes(fill = nilai_plot), color = "white", linewidth = 0.4) +
scale_fill_distiller(
palette = palet,
direction = arah_palet,
name = var_col,
labels = label_comma(big.mark = ".", decimal.mark = ","),
guide = guide_colorbar(barwidth = 0.8, barheight = 8,
title.position = "top")
) +
geom_text_repel(
data = label_df,
aes(x = lx, y = ly, label = wilayah),
size = 2.2,
fontface = "bold",
color = "black",
bg.color = "white",
bg.r = 0.15,
segment.color = "grey50",
segment.size = 0.3,
max.overlaps = 50,
min.segment.length = 0.1,
force = 1.5,
seed = 42
) +
labs(title = judul, subtitle = subjudul) +
tema_peta
}
# ============================================================
# PETA 1 – SEBARAN VARIABEL Y (Jumlah Kasus / Count)
# ============================================================
p_Y <- buat_peta_khoropleth(
sf_data = data_sf,
var_col = "Y_count",
judul = "Peta Sebaran Variabel Y",
subjudul = "Jumlah Kasus per Kabupaten/Kota di Jawa Tengah",
label_df = df_label,
palet = "YlOrRd",
arah_palet = 1
)
print(p_Y)

ggsave("peta_Y.png", p_Y, width = 12, height = 8, dpi = 200)
# ============================================================
# PETA 2–5 – SEBARAN VARIABEL X1, X2, X3, X4
# ============================================================
info_x <- list(
X1 = list(judul = "Peta Sebaran Variabel X1",
subjudul = "Kabupaten/Kota di Jawa Tengah",
palet = "Blues", arah = 1),
X2 = list(judul = "Peta Sebaran Variabel X2",
subjudul = "Kabupaten/Kota di Jawa Tengah",
palet = "Greens", arah = 1),
X3 = list(judul = "Peta Sebaran Variabel X3",
subjudul = "Kabupaten/Kota di Jawa Tengah",
palet = "Purples", arah = 1),
X4 = list(judul = "Peta Sebaran Variabel X4",
subjudul = "Kabupaten/Kota di Jawa Tengah",
palet = "Oranges", arah = 1)
)
peta_list <- list()
for (xv in names(info_x)) {
info <- info_x[[xv]]
p <- buat_peta_khoropleth(
sf_data = data_sf,
var_col = xv,
judul = info$judul,
subjudul = info$subjudul,
label_df = df_label,
palet = info$palet,
arah_palet = info$arah
)
peta_list[[xv]] <- p
print(p)
ggsave(paste0("peta_", xv, ".png"), p, width = 12, height = 8, dpi = 200)
}




# ============================================================
# PETA 6 – PENGELOMPOKAN WILAYAH BERDASARKAN SIGNIFIKANSI GWNBR
# ============================================================
# Pastikan kolom Kelompok_Signifikan sudah ada (dibuat di chunk 21)
# Bila belum ada, jalankan ulang chunk 21 terlebih dahulu.
if (!("Kelompok_Signifikan" %in% names(data_sf))) {
stop("Kolom Kelompok_Signifikan belum ada. Jalankan chunk 21 terlebih dahulu.")
}
# Buat palet warna kategorikal yang kontras
kelompok_unik <- sort(unique(data_sf$Kelompok_Signifikan))
n_kelompok <- length(kelompok_unik)
# Palet kontras: gabungkan beberapa set warna yang tajam
palet_kontras <- c(
"#E63946", # merah terang
"#2A9D8F", # tosca
"#F4A261", # oranye hangat
"#457B9D", # biru tua
"#8338EC", # ungu cerah
"#06D6A0", # hijau mint
"#FFB703", # kuning amber
"#FB5607", # oranye tua
"#3A86FF", # biru cerah
"#FFBE0B", # kuning
"#D62246", # merah tua
"#4CC9F0", # biru langit
"#B5179E", # magenta
"#4D908E", # hijau kebiruan
"#F72585", # pink terang
"#90E0EF", # biru pastel kontras
"#43AA8B", # hijau sage
"#577590" # abu kebiruan
)
# Kalau jumlah kelompok > panjang vektor, pakai rainbow
if (n_kelompok > length(palet_kontras)) {
palet_pakai <- hcl.colors(n_kelompok, palette = "Dynamic")
} else {
palet_pakai <- palet_kontras[seq_len(n_kelompok)]
}
names(palet_pakai) <- kelompok_unik
p_sig <- ggplot(data_sf) +
geom_sf(
aes(fill = Kelompok_Signifikan),
color = "white",
linewidth = 0.45
) +
scale_fill_manual(
values = palet_pakai,
name = "Variabel Signifikan",
guide = guide_legend(
ncol = 1,
byrow = TRUE,
keywidth = unit(0.6, "cm"),
keyheight = unit(0.5, "cm"),
override.aes = list(color = "white", linewidth = 0.3)
)
) +
geom_text_repel(
data = df_label,
aes(x = lx, y = ly, label = wilayah),
size = 2.2,
fontface = "bold",
color = "black",
bg.color = "white",
bg.r = 0.15,
segment.color = "grey50",
segment.size = 0.3,
max.overlaps = 50,
min.segment.length = 0.1,
force = 1.5,
seed = 42
) +
labs(
title = "Peta Pengelompokan Wilayah Berdasarkan Variabel Signifikan GWNBR",
subtitle = "Kabupaten/Kota di Jawa Tengah"
) +
tema_peta +
theme(
legend.text = element_text(size = 7.5),
legend.title = element_text(size = 9, face = "bold")
)
print(p_sig)

ggsave("peta_signifikansi_gwnbr.png", p_sig, width = 14, height = 9, dpi = 200)
# ============================================================
# BONUS: Panel 6 peta sekaligus (opsional, butuh patchwork)
# ============================================================
if (requireNamespace("patchwork", quietly = TRUE)) {
library(patchwork)
panel_semua <- (p_Y | peta_list$X1 | peta_list$X2) /
(peta_list$X3 | peta_list$X4 | p_sig) +
plot_annotation(
title = "Analisis Spasial GWNBR – Jawa Tengah",
caption = "Sumber: Data Penelitian | Disusun: Nisrina Aisyah & Nayli Kurnia Ilahi",
theme = theme(
plot.title = element_text(face = "bold", size = 16, hjust = 0.5),
plot.caption = element_text(size = 8, color = "grey50")
)
)
ggsave("panel_semua_peta.png", panel_semua,
width = 26, height = 16, dpi = 180)
cat("Panel lengkap disimpan: panel_semua_peta.png\n")
} else {
cat("Install patchwork untuk panel gabungan: install.packages('patchwork')\n")
}
##
## Attaching package: 'patchwork'
## The following object is masked from 'package:MASS':
##
## area
## Panel lengkap disimpan: panel_semua_peta.png
cat("\nSemua peta berhasil dibuat dan disimpan.\n")
##
## Semua peta berhasil dibuat dan disimpan.