knitr::opts_chunk$set( 
  echo = TRUE 
  )

# ==============================================================================
# LOAD PACKAGE
# ==============================================================================

library(sf)
library(dplyr)
library(ggplot2)
library(spdep)
library(spatstat)
library(gstat)
library(sp)
library(viridis)
library(readr)
library(stringr)

# ==============================================================================
# PENDAHULUAN
# ==============================================================================
cat("Praktikum Statistika Spasial\n")
## Praktikum Statistika Spasial
cat("Analisis Kemiskinan dan Curah Hujan Jawa Tengah\n\n")
## Analisis Kemiskinan dan Curah Hujan Jawa Tengah
# ==============================================================================
# MENENTUKAN LOKASI FILE
# ==============================================================================

path_shp <- "C:/Users/Lutfi/Downloads/shp_jateng/shp_gadm/gadm41_IDN_2.shp"

path_kemiskinan <- "C:/Users/Lutfi/Downloads/shp_jateng/Kemiskinan Menurut Kabupaten_Kota di Provinsi Jawa Tengah, 2024.csv"

path_curahhujan <- "C:/Users/Lutfi/Downloads/shp_jateng/POWER_Regional_Monthly_2023_2024.csv"

# ==============================================================================
# BAB 1 - PERSIAPAN DATA
# ==============================================================================

cat("\n====================================================\n")
## 
## ====================================================
cat("BAB 1 - PERSIAPAN DATA\n")
## BAB 1 - PERSIAPAN DATA
cat("====================================================\n")
## ====================================================
# ------------------------------------------------------------------------------
# 1A. MEMBACA SHAPEFILE
# ------------------------------------------------------------------------------

cat("\nMembaca shapefile Indonesia...\n")
## 
## Membaca shapefile Indonesia...
shp_indonesia <- st_read(path_shp)
## Reading layer `gadm41_IDN_2' from data source 
##   `C:\Users\Lutfi\Downloads\shp_jateng\shp_gadm\gadm41_IDN_2.shp' 
##   using driver `ESRI Shapefile'
## Simple feature collection with 502 features and 13 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: 95.00971 ymin: -11.00761 xmax: 141.0194 ymax: 6.076941
## Geodetic CRS:  WGS 84
cat("\nNama kolom:\n")
## 
## Nama kolom:
print(names(shp_indonesia))
##  [1] "GID_2"     "GID_0"     "COUNTRY"   "GID_1"     "NAME_1"    "NL_NAME_1"
##  [7] "NAME_2"    "VARNAME_2" "NL_NAME_2" "TYPE_2"    "ENGTYPE_2" "CC_2"     
## [13] "HASC_2"    "geometry"
# Filter Jawa Tengah
shp_jateng <- shp_indonesia %>%
  filter(NAME_1 == "Jawa Tengah")

cat("\nJumlah kabupaten/kota Jawa Tengah:\n")
## 
## Jumlah kabupaten/kota Jawa Tengah:
print(nrow(shp_jateng))
## [1] 36
print(shp_jateng[, c("NAME_2", "geometry")])
## Simple feature collection with 36 features and 1 field
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: 108.5559 ymin: -8.21193 xmax: 111.6914 ymax: -5.725698
## Geodetic CRS:  WGS 84
## First 10 features:
##          NAME_2                       geometry
## 1  Banjarnegara MULTIPOLYGON (((109.42 -7.5...
## 2      Banyumas MULTIPOLYGON (((109.4411 -7...
## 3        Batang MULTIPOLYGON (((109.917 -7....
## 4         Blora MULTIPOLYGON (((111.4427 -7...
## 5      Boyolali MULTIPOLYGON (((110.534 -7....
## 6        Brebes MULTIPOLYGON (((109.0322 -7...
## 7       Cilacap MULTIPOLYGON (((109.3856 -7...
## 8         Demak MULTIPOLYGON (((110.5618 -7...
## 9      Grobogan MULTIPOLYGON (((110.9202 -7...
## 10       Jepara MULTIPOLYGON (((110.7048 -6...
# Peta dasar Jawa Tengah
plot(
  st_geometry(shp_jateng),
  main = "Peta Jawa Tengah - 35 Kabupaten/Kota"
)

# ------------------------------------------------------------------------------
# 1B. MEMBACA DATA KEMISKINAN
# ------------------------------------------------------------------------------

cat("\nMembaca data kemiskinan...\n")
## 
## Membaca data kemiskinan...
kemiskinan_raw <- read_csv(
  path_kemiskinan,
  skip = 3,
  col_names = FALSE
)

colnames(kemiskinan_raw) <- c(
  "nama_wilayah",
  "garis_kemiskinan",
  "jumlah_miskin_ribu",
  "persen_miskin"
)

cat("\nData awal kemiskinan:\n")
## 
## Data awal kemiskinan:
print(head(kemiskinan_raw))
## # A tibble: 6 × 4
##   nama_wilayah                garis_kemiskinan jumlah_miskin_ribu persen_miskin
##   <chr>                                  <dbl>              <dbl>         <dbl>
## 1 <NA>                                    2024              2024         2024  
## 2 3300 PROVINSI JAWA TENGAH             507001              3704.          10.5
## 3 3301 Kabupaten Cilacap                441093               186.          10.7
## 4 3302 Kabupaten Banyumas               500861               208.          12.0
## 5 3303 Kabupaten Purbalingga            460870               137.          14.2
## 6 3304 Kabupaten Banjarnegara           398344               138.          14.7
# Membersihkan data
kemiskinan <- kemiskinan_raw %>%
  slice(-1) %>%
  filter(!is.na(nama_wilayah)) %>%
  mutate(
    nama_bersih = str_trim(
      str_replace(nama_wilayah, "^\\d+ ", "")
    ),
    persen_miskin = as.numeric(persen_miskin),
    jumlah_miskin_ribu = as.numeric(jumlah_miskin_ribu),
    garis_kemiskinan = as.numeric(garis_kemiskinan)
  )

cat("\nData setelah dibersihkan:\n")
## 
## Data setelah dibersihkan:
print(kemiskinan[, c("nama_bersih", "persen_miskin")])
## # A tibble: 36 × 2
##    nama_bersih            persen_miskin
##    <chr>                          <dbl>
##  1 PROVINSI JAWA TENGAH           10.5 
##  2 Kabupaten Cilacap              10.7 
##  3 Kabupaten Banyumas             12.0 
##  4 Kabupaten Purbalingga          14.2 
##  5 Kabupaten Banjarnegara         14.7 
##  6 Kabupaten Kebumen              15.7 
##  7 Kabupaten Purworejo            10.9 
##  8 Kabupaten Wonosobo             15.3 
##  9 Kabupaten Magelang             10.8 
## 10 Kabupaten Boyolali              9.63
## # ℹ 26 more rows
# ------------------------------------------------------------------------------
# 1C. PENYESUAIAN NAMA UNTUK JOIN
# ------------------------------------------------------------------------------

cat("\nNama wilayah SHP:\n")
## 
## Nama wilayah SHP:
print(sort(shp_jateng$NAME_2))
##  [1] "Banjarnegara"     "Banyumas"         "Batang"           "Blora"           
##  [5] "Boyolali"         "Brebes"           "Cilacap"          "Demak"           
##  [9] "Grobogan"         "Jepara"           "Karanganyar"      "Kebumen"         
## [13] "Kendal"           "Klaten"           "Kota Magelang"    "Kota Pekalongan" 
## [17] "Kota Semarang"    "Kota Tegal"       "Kudus"            "Magelang"        
## [21] "Pati"             "Pekalongan"       "Pemalang"         "Purbalingga"     
## [25] "Purworejo"        "Rembang"          "Salatiga"         "Semarang"        
## [29] "Sragen"           "Sukoharjo"        "Surakarta"        "Tegal"           
## [33] "Temanggung"       "Waduk Kedungombo" "Wonogiri"         "Wonosobo"
cat("\nNama wilayah BPS:\n")
## 
## Nama wilayah BPS:
print(sort(kemiskinan$nama_bersih))
##  [1] "Kabupaten Banjarnegara" "Kabupaten Banyumas"     "Kabupaten Batang"      
##  [4] "Kabupaten Blora"        "Kabupaten Boyolali"     "Kabupaten Brebes"      
##  [7] "Kabupaten Cilacap"      "Kabupaten Demak"        "Kabupaten Grobogan"    
## [10] "Kabupaten Jepara"       "Kabupaten Karanganyar"  "Kabupaten Kebumen"     
## [13] "Kabupaten Kendal"       "Kabupaten Klaten"       "Kabupaten Kudus"       
## [16] "Kabupaten Magelang"     "Kabupaten Pati"         "Kabupaten Pekalongan"  
## [19] "Kabupaten Pemalang"     "Kabupaten Purbalingga"  "Kabupaten Purworejo"   
## [22] "Kabupaten Rembang"      "Kabupaten Semarang"     "Kabupaten Sragen"      
## [25] "Kabupaten Sukoharjo"    "Kabupaten Tegal"        "Kabupaten Temanggung"  
## [28] "Kabupaten Wonogiri"     "Kabupaten Wonosobo"     "Kota Magelang"         
## [31] "Kota Pekalongan"        "Kota Salatiga"          "Kota Semarang"         
## [34] "Kota Surakarta"         "Kota Tegal"             "PROVINSI JAWA TENGAH"
# Hapus Waduk Kedungombo
shp_jateng <- shp_jateng %>%
  filter(NAME_2 != "Waduk Kedungombo")

# Membuat nama kunci
shp_jateng <- shp_jateng %>%
  mutate(
    nama_kunci = str_to_lower(
      str_trim(
        str_replace_all(
          NAME_2,
          c("Kabupaten " = "", "Kota " = "")
        )
      )
    )
  ) %>%
  mutate(
    nama_kunci = ifelse(
      NAME_2 == "Kota Magelang",
      "kota magelang",
      ifelse(
        NAME_2 == "Magelang",
        "kabupaten magelang",
        nama_kunci
      )
    )
  )

kemiskinan <- kemiskinan %>%
  mutate(
    nama_kunci = str_to_lower(
      str_trim(
        str_replace_all(
          nama_bersih,
          c("Kabupaten " = "", "Kota " = "")
        )
      )
    )
  ) %>%
  mutate(
    nama_kunci = ifelse(
      nama_bersih == "Kota Magelang",
      "kota magelang",
      ifelse(
        nama_bersih == "Kabupaten Magelang",
        "kabupaten magelang",
        nama_kunci
      )
    )
  )

# Cek data yang tidak cocok
tidak_cocok <- anti_join(
  data.frame(nama_kunci = shp_jateng$nama_kunci),
  data.frame(nama_kunci = kemiskinan$nama_kunci),
  by = "nama_kunci"
)

cat("\nData yang tidak cocok:\n")
## 
## Data yang tidak cocok:
print(tidak_cocok)
## [1] nama_kunci
## <0 rows> (or 0-length row.names)
# ------------------------------------------------------------------------------
# 1D. MENGGABUNGKAN DATA
# ------------------------------------------------------------------------------

cat("\nMenggabungkan data shapefile dan kemiskinan...\n")
## 
## Menggabungkan data shapefile dan kemiskinan...
shp_gabung <- shp_jateng %>%
  left_join(
    kemiskinan %>%
      select(
        nama_kunci,
        persen_miskin,
        jumlah_miskin_ribu,
        garis_kemiskinan
      ),
    by = "nama_kunci"
  )

cat("\nJumlah missing value:\n")
## 
## Jumlah missing value:
print(sum(is.na(shp_gabung$persen_miskin)))
## [1] 0
# Peta kemiskinan
ggplot(shp_gabung) +
  geom_sf(aes(fill = persen_miskin)) +
  scale_fill_viridis_c(
    name = "% Miskin",
    option = "plasma"
  ) +
  labs(
    title = "Persentase Kemiskinan Jawa Tengah 2024",
    subtitle = "Sumber: BPS Jawa Tengah"
  ) +
  theme_minimal()

# ------------------------------------------------------------------------------
# 1E. DATA CURAH HUJAN NASA POWER
# ------------------------------------------------------------------------------

cat("\nMembaca data curah hujan NASA POWER...\n")
## 
## Membaca data curah hujan NASA POWER...
curahhujan_raw <- read_csv(
  path_curahhujan,
  skip = 9
)

print(head(curahhujan_raw))
## # A tibble: 6 × 17
##   PARAMETER     YEAR   LAT   LON   JAN   FEB   MAR   APR   MAY   JUN   JUL   AUG
##   <chr>        <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 PRECTOTCORR…  2023  -6    109.  281.  294.  149.  200.  58.5  69.0  43.8  7.73
## 2 PRECTOTCORR…  2023  -6    109.  316.  303.  115.  175.  59.9  69.1  74.4 11.7 
## 3 PRECTOTCORR…  2023  -6    110   312.  307.  110.  165.  58.9  68.7  81.4 12.4 
## 4 PRECTOTCORR…  2023  -6    111.  314.  382.  125.  139.  64.0  65.1 116.  13.9 
## 5 PRECTOTCORR…  2023  -6    111.  284.  416.  138.  140.  67.9  62.8  91.8 13.4 
## 6 PRECTOTCORR…  2023  -6.5  109.  358.  392.  216.  322.  84.8  63.0  92.8  4.7 
## # ℹ 5 more variables: SEP <dbl>, OCT <dbl>, NOV <dbl>, DEC <dbl>, ANN <dbl>
curahhujan <- curahhujan_raw %>%
  filter(YEAR == 2023) %>%
  select(
    LAT,
    LON,
    curah_hujan_tahunan = ANN
  ) %>%
  filter(curah_hujan_tahunan != -999)

cat("\nJumlah titik curah hujan:\n")
## 
## Jumlah titik curah hujan:
print(nrow(curahhujan))
## [1] 30
print(head(curahhujan))
## # A tibble: 6 × 3
##     LAT   LON curah_hujan_tahunan
##   <dbl> <dbl>               <dbl>
## 1  -6    109.               1413.
## 2  -6    109.               1481.
## 3  -6    110                1479.
## 4  -6    111.               1595.
## 5  -6    111.               1614.
## 6  -6.5  109.               1909.
# Visualisasi titik curah hujan
ggplot(
  curahhujan,
  aes(
    x = LON,
    y = LAT,
    color = curah_hujan_tahunan
  )
) +
  geom_point(size = 3) +
  scale_color_viridis_c(
    name = "CH Tahunan\n(mm)"
  ) +
  labs(
    title = "Titik Curah Hujan NASA POWER 2023",
    subtitle = "Wilayah Jawa Tengah",
    x = "Longitude",
    y = "Latitude"
  ) +
  theme_minimal()

# ==============================================================================
# BAB 2 - ANALISIS POLA SPASIAL
# ==============================================================================

cat("\n====================================================\n")
## 
## ====================================================
cat("BAB 2 - ANALISIS POLA SPASIAL\n")
## BAB 2 - ANALISIS POLA SPASIAL
cat("====================================================\n")
## ====================================================
# Konversi ke format spatstat
centroid <- st_centroid(shp_gabung)
coords <- st_coordinates(centroid)

bbox_jateng <- st_bbox(shp_gabung)

window_jateng <- owin(
  xrange = c(
    bbox_jateng["xmin"],
    bbox_jateng["xmax"]
  ),
  yrange = c(
    bbox_jateng["ymin"],
    bbox_jateng["ymax"]
  )
)

pola_titik <- ppp(
  x = coords[,1],
  y = coords[,2],
  window = window_jateng,
  marks = shp_gabung$persen_miskin
)

# Plot sebaran titik
plot(
  pola_titik,
  main = "Sebaran Centroid Kabupaten/Kota Jawa Tengah"
)

# Quadrat test
qt <- quadrat.test(
  pola_titik,
  nx = 5,
  ny = 5
)

cat("\nHasil Quadrat Test:\n")
## 
## Hasil Quadrat Test:
print(qt)
## 
##  Chi-squared test of CSR using quadrat counts
## 
## data:  pola_titik
## X2 = 85.22, df = 24, p-value = 1.756e-08
## alternative hypothesis: two.sided
## 
## Quadrats: 5 by 5 grid of tiles
plot(
  qt,
  main = "Quadrat Test - Pola Spasial Jawa Tengah"
)

# Fungsi G
G_obs <- Gest(pola_titik)

plot(
  G_obs,
  main = "Fungsi G - KNN Analysis"
)

# Kernel Density
kde <- density(
  pola_titik,
  sigma = 0.5
)

plot(
  kde,
  main = "Kernel Density"
)

contour(kde, add = TRUE)

# Fungsi L
L_obs <- Lest(pola_titik)

plot(
  L_obs,
  main = "Fungsi L (Ripley's K)"
)

# ==============================================================================
# BAB 3 - MATRIKS PEMBOBOT SPASIAL
# ==============================================================================

cat("\n====================================================\n")
## 
## ====================================================
cat("BAB 3 - MATRIKS PEMBOBOT SPASIAL\n")
## BAB 3 - MATRIKS PEMBOBOT SPASIAL
cat("====================================================\n")
## ====================================================
# ------------------------------------------------------------------------------
# 3A. MATRIKS CONTIGUITY - QUEEN
# ------------------------------------------------------------------------------

cat("\nMembuat matriks Queen Contiguity...\n")
## 
## Membuat matriks Queen Contiguity...
nb_queen <- poly2nb(
  shp_gabung,
  queen = TRUE
)

summary(nb_queen)
## Neighbour list object:
## Number of regions: 41 
## Number of nonzero links: 214 
## Percentage nonzero weights: 12.73052 
## Average number of links: 5.219512 
## Link number distribution:
## 
##  1  2  3  4  5  6  7  8  9 10 
##  1  3  7  5  8  4  7  3  1  2 
## 1 least connected region:
## 15 with 1 link
## 2 most connected regions:
## 32 33 with 10 links
W_queen <- nb2listw(
  nb_queen,
  style = "W",
  zero.policy = TRUE
)

plot(
  st_geometry(shp_gabung),
  border = "grey",
  main = "Matriks Queen Contiguity"
)

plot(
  nb_queen,
  coords,
  add = TRUE,
  col = "red",
  lwd = 0.5
)

# ------------------------------------------------------------------------------
# 3B. MATRIKS CONTIGUITY - ROOK
# ------------------------------------------------------------------------------

cat("\nMembuat matriks Rook Contiguity...\n")
## 
## Membuat matriks Rook Contiguity...
nb_rook <- poly2nb(
  shp_gabung,
  queen = FALSE
)

summary(nb_rook)
## Neighbour list object:
## Number of regions: 41 
## Number of nonzero links: 212 
## Percentage nonzero weights: 12.61154 
## Average number of links: 5.170732 
## Link number distribution:
## 
##  1  2  3  4  5  6  7  8  9 10 
##  1  4  6  5  8  4  8  2  1  2 
## 1 least connected region:
## 15 with 1 link
## 2 most connected regions:
## 32 33 with 10 links
W_rook <- nb2listw(
  nb_rook,
  style = "W",
  zero.policy = TRUE
)

plot(
  st_geometry(shp_gabung),
  border = "grey",
  main = "Matriks Rook Contiguity"
)

plot(
  nb_rook,
  coords,
  add = TRUE,
  col = "blue",
  lwd = 0.5
)

# ------------------------------------------------------------------------------
# 3C. MATRIKS BERBASIS JARAK (DISTANCE-BASED)
# ------------------------------------------------------------------------------

cat("\nMembuat matriks Distance-Based...\n")
## 
## Membuat matriks Distance-Based...
# Menentukan jarak kritis
jarak_kritis <- max(
  unlist(
    nbdists(nb_queen, coords)
  )
)

cat("\nJarak kritis:\n")
## 
## Jarak kritis:
print(jarak_kritis)
## [1] 0.74543
# Membuat tetangga berdasarkan jarak
nb_jarak <- dnearneigh(
  coords,
  d1 = 0,
  d2 = jarak_kritis
)

summary(nb_jarak)
## Neighbour list object:
## Number of regions: 41 
## Number of nonzero links: 632 
## Percentage nonzero weights: 37.59667 
## Average number of links: 15.41463 
## Link number distribution:
## 
##  5  6  7  9 10 11 12 13 14 16 17 18 19 20 21 
##  1  1  2  2  1  1  1  5  2  7  2  2  4  5  5 
## 1 least connected region:
## 30 with 5 links
## 5 most connected regions:
## 3 18 19 39 41 with 21 links
W_jarak <- nb2listw(
  nb_jarak,
  style = "W",
  zero.policy = TRUE
)

plot(
  st_geometry(shp_gabung),
  border = "grey",
  main = "Matriks Distance-Based"
)

plot(
  nb_jarak,
  coords,
  add = TRUE,
  col = "darkgreen",
  lwd = 0.5
)

# ------------------------------------------------------------------------------
# 3D. MATRIKS K-NEAREST NEIGHBOR (KNN)
# ------------------------------------------------------------------------------

cat("\nMembuat matriks K-Nearest Neighbor...\n")
## 
## Membuat matriks K-Nearest Neighbor...
# Menggunakan 5 tetangga terdekat
nb_knn <- knn2nb(
  knearneigh(coords, k = 5)
)

summary(nb_knn)
## Neighbour list object:
## Number of regions: 41 
## Number of nonzero links: 205 
## Percentage nonzero weights: 12.19512 
## Average number of links: 5 
## Non-symmetric neighbours list
## Link number distribution:
## 
##  5 
## 41 
## 41 least connected regions:
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 with 5 links
## 41 most connected regions:
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 with 5 links
W_knn <- nb2listw(
  nb_knn,
  style = "W",
  zero.policy = TRUE
)

plot(
  st_geometry(shp_gabung),
  border = "grey",
  main = "Matriks KNN (k = 5)"
)

plot(
  nb_knn,
  coords,
  add = TRUE,
  col = "purple",
  lwd = 0.5
)

cat("\n====================================================\n")
## 
## ====================================================
cat("SEMUA MATRIKS PEMBOBOT BERHASIL DIBUAT\n")
## SEMUA MATRIKS PEMBOBOT BERHASIL DIBUAT
cat("====================================================\n")
## ====================================================
# ==============================================================================
# BAB 4 - AUTOKORELASI SPASIAL
# ==============================================================================

cat("\n====================================================\n")
## 
## ====================================================
cat("BAB 4 - AUTOKORELASI SPASIAL\n")
## BAB 4 - AUTOKORELASI SPASIAL
cat("====================================================\n")
## ====================================================
y <- shp_gabung$persen_miskin

# Moran
moran_queen <- moran.test(
  y,
  W_queen,
  zero.policy = TRUE
)

moran_rook <- moran.test(
  y,
  W_rook,
  zero.policy = TRUE
)

moran_jarak <- moran.test(
  y,
  W_jarak,
  zero.policy = TRUE
)

moran_knn <- moran.test(
  y,
  W_knn,
  zero.policy = TRUE
)

cat("\n===== MORAN GLOBAL =====\n")
## 
## ===== MORAN GLOBAL =====
print(moran_queen)
## 
##  Moran I test under randomisation
## 
## data:  y  
## weights: W_queen    
## 
## Moran I statistic standard deviate = 2.5932, p-value = 0.004754
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##       0.226084817      -0.025000000       0.009374687
print(moran_rook)
## 
##  Moran I test under randomisation
## 
## data:  y  
## weights: W_rook    
## 
## Moran I statistic standard deviate = 2.514, p-value = 0.005968
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##       0.220591029      -0.025000000       0.009542845
print(moran_jarak)
## 
##  Moran I test under randomisation
## 
## data:  y  
## weights: W_jarak    
## 
## Moran I statistic standard deviate = 1.5985, p-value = 0.05497
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##       0.050742843      -0.025000000       0.002245306
print(moran_knn)
## 
##  Moran I test under randomisation
## 
## data:  y  
## weights: W_knn    
## 
## Moran I statistic standard deviate = 2.4638, p-value = 0.006874
## alternative hypothesis: greater
## sample estimates:
## Moran I statistic       Expectation          Variance 
##       0.188592660      -0.025000000       0.007515737
# Moran scatterplot
moran.plot(
  y,
  W_queen,
  labels = shp_gabung$NAME_2,
  xlab = "Persentase Kemiskinan",
  ylab = "Spatial Lag",
  main = "Moran Scatterplot"
)

# ------------------------------------------------------------------------------
# 4B. INDEKS GEARY GLOBAL
# ------------------------------------------------------------------------------
# Mirip Moran tetapi lebih sensitif terhadap perbedaan lokal
# Range:
#   C < 1  -> clustered (autokorelasi positif)
#   C > 1  -> dispersed (autokorelasi negatif)
#   C = 1  -> random

cat("\n====================================================\n")
## 
## ====================================================
cat("INDEKS GEARY GLOBAL\n")
## INDEKS GEARY GLOBAL
cat("====================================================\n")
## ====================================================
# Queen Contiguity
geary_queen <- geary.test(
  y,
  W_queen,
  zero.policy = TRUE
)

# Rook Contiguity
geary_rook <- geary.test(
  y,
  W_rook,
  zero.policy = TRUE
)

# Distance-Based
geary_jarak <- geary.test(
  y,
  W_jarak,
  zero.policy = TRUE
)

# K-Nearest Neighbor
geary_knn <- geary.test(
  y,
  W_knn,
  zero.policy = TRUE
)

# Menampilkan hasil
cat(
  "\nQueen Contiguity :",
  round(geary_queen$estimate[1], 4),
  "| p-value:",
  round(geary_queen$p.value, 4),
  "\n"
)
## 
## Queen Contiguity : 0.7408 | p-value: 0.0065
cat(
  "Rook Contiguity  :",
  round(geary_rook$estimate[1], 4),
  "| p-value:",
  round(geary_rook$p.value, 4),
  "\n"
)
## Rook Contiguity  : 0.7475 | p-value: 0.0082
cat(
  "Distance-Based   :",
  round(geary_jarak$estimate[1], 4),
  "| p-value:",
  round(geary_jarak$p.value, 4),
  "\n"
)
## Distance-Based   : 0.936 | p-value: 0.1024
cat(
  "KNN (k = 5)      :",
  round(geary_knn$estimate[1], 4),
  "| p-value:",
  round(geary_knn$p.value, 4),
  "\n"
)
## KNN (k = 5)      : 0.8024 | p-value: 0.0149
cat("\n====================================================\n")
## 
## ====================================================
cat("INTERPRETASI GEARY\n")
## INTERPRETASI GEARY
cat("====================================================\n")
## ====================================================
cat("C < 1  dan p-value < 0.05 -> Clustered\n")
## C < 1  dan p-value < 0.05 -> Clustered
cat("C > 1  dan p-value < 0.05 -> Dispersed\n")
## C > 1  dan p-value < 0.05 -> Dispersed
cat("C ≈ 1                     -> Random\n")
## C ≈ 1                     -> Random
# ------------------------------------------------------------------------------
# 4C. GETIS-ORD G GLOBAL
# ------------------------------------------------------------------------------
# Mendeteksi apakah nilai tinggi/rendah mengelompok secara global

cat("\n====================================================\n")
## 
## ====================================================
cat("GETIS-ORD G GLOBAL\n")
## GETIS-ORD G GLOBAL
cat("====================================================\n")
## ====================================================
# Catatan:
# Getis-Ord menggunakan matriks non-standardisasi
# sehingga style = "B"

# Queen Binary Weight
W_queen_B <- nb2listw(
  nb_queen,
  style = "B",
  zero.policy = TRUE
)

# Rook Binary Weight
W_rook_B <- nb2listw(
  nb_rook,
  style = "B",
  zero.policy = TRUE
)

# Getis-Ord Queen
go_queen <- globalG.test(
  y,
  W_queen_B,
  zero.policy = TRUE
)

# Getis-Ord Rook
go_rook <- globalG.test(
  y,
  W_rook_B,
  zero.policy = TRUE
)

# Menampilkan hasil
cat(
  "\nQueen Contiguity :",
  round(go_queen$estimate[1], 4),
  "| p-value:",
  round(go_queen$p.value, 4),
  "\n"
)
## 
## Queen Contiguity : 0.1355 | p-value: 0.1995
cat(
  "Rook Contiguity  :",
  round(go_rook$estimate[1], 4),
  "| p-value:",
  round(go_rook$p.value, 4),
  "\n"
)
## Rook Contiguity  : 0.1338 | p-value: 0.224
cat("\n====================================================\n")
## 
## ====================================================
cat("INTERPRETASI GETIS-ORD G\n")
## INTERPRETASI GETIS-ORD G
cat("====================================================\n")
## ====================================================
cat("G > E(G) dan p-value < 0.05 -> Hot Spot Global\n")
## G > E(G) dan p-value < 0.05 -> Hot Spot Global
cat("G < E(G) dan p-value < 0.05 -> Cold Spot Global\n")
## G < E(G) dan p-value < 0.05 -> Cold Spot Global
# ------------------------------------------------------------------------------
# 4D. INDEKS MORAN LOKAL (LISA)
# ------------------------------------------------------------------------------
# Mendeteksi cluster dan outlier spasial di level wilayah individual
# LISA

lisa <- localmoran(
  y,
  W_queen,
  zero.policy = TRUE
)

shp_gabung$lisa_I <- lisa[,1]
shp_gabung$lisa_pval <- lisa[,5]

mean_y <- mean(y, na.rm = TRUE)

lag_y <- lag.listw(
  W_queen,
  y,
  zero.policy = TRUE
)

shp_gabung$lisa_kategori <- "Not Significant"

shp_gabung$lisa_kategori[
  y > mean_y &
  lag_y > mean_y &
  lisa[,5] < 0.05
] <- "High-High"

shp_gabung$lisa_kategori[
  y < mean_y &
  lag_y < mean_y &
  lisa[,5] < 0.05
] <- "Low-Low"

shp_gabung$lisa_kategori[
  y > mean_y &
  lag_y < mean_y &
  lisa[,5] < 0.05
] <- "High-Low"

shp_gabung$lisa_kategori[
  y < mean_y &
  lag_y > mean_y &
  lisa[,5] < 0.05
] <- "Low-High"

warna_lisa <- c(
  "High-High" = "#d7191c",
  "Low-Low" = "#2c7bb6",
  "High-Low" = "#fdae61",
  "Low-High" = "#abd9e9",
  "Not Significant" = "#eeeeee"
)

ggplot(shp_gabung) +
  geom_sf(
    aes(fill = lisa_kategori),
    color = "white",
    size = 0.3
  ) +
  scale_fill_manual(
    values = warna_lisa,
    name = "Kategori LISA"
  ) +
  labs(
    title = "Peta LISA Jawa Tengah 2024"
  ) +
  theme_minimal()

# ------------------------------------------------------------------------------
# 4E. GETIS-ORD G* LOKAL (HOT SPOT ANALYSIS)
# ------------------------------------------------------------------------------
# Mendeteksi hot spot dan cold spot secara lokal

cat("\n====================================================\n")
## 
## ====================================================
cat("GETIS-ORD G* LOKAL\n")
## GETIS-ORD G* LOKAL
cat("====================================================\n")
## ====================================================
# Matriks yang menyertakan dirinya sendiri
nb_queen_self <- include.self(nb_queen)

W_queen_self <- nb2listw(
  nb_queen_self,
  style = "B",
  zero.policy = TRUE
)

# Menghitung Getis-Ord G* lokal
go_lokal <- localG(
  y,
  W_queen_self,
  zero.policy = TRUE
)

# Menyimpan hasil
shp_gabung$Gstar <- as.numeric(go_lokal)

shp_gabung$Gstar_sig <- ifelse(
  abs(shp_gabung$Gstar) > 1.96,
  "Signifikan",
  "Tidak Signifikan"
)

# Visualisasi Hot Spot / Cold Spot
ggplot(shp_gabung) +
  geom_sf(
    aes(fill = Gstar),
    color = "white",
    size = 0.3
  ) +
  scale_fill_gradient2(
    low = "#2c7bb6",
    mid = "#eeeeee",
    high = "#d7191c",
    midpoint = 0,
    name = "Z-score G*"
  ) +
  labs(
    title = "Getis-Ord G* Lokal - Hot/Cold Spot Kemiskinan",
    subtitle = "Merah = Hot Spot | Biru = Cold Spot"
  ) +
  theme_minimal()

# ------------------------------------------------------------------------------
# 4F. RANGKUMAN PERBANDINGAN SEMUA INDEKS
# ------------------------------------------------------------------------------

cat("\n====================================================\n")
## 
## ====================================================
cat("RANGKUMAN PERBANDINGAN INDEKS AUTOKORELASI\n")
## RANGKUMAN PERBANDINGAN INDEKS AUTOKORELASI
cat("====================================================\n")
## ====================================================
cat(
  sprintf(
    "%-25s %-12s %-12s\n",
    "Indeks",
    "Nilai",
    "p-value"
  )
)
## Indeks                    Nilai        p-value
cat(
  sprintf(
    "%-25s %-12s %-12s\n",
    "Moran (Queen)",
    round(moran_queen$estimate[1], 4),
    round(moran_queen$p.value, 4)
  )
)
## Moran (Queen)             0.2261       0.0048
cat(
  sprintf(
    "%-25s %-12s %-12s\n",
    "Moran (Rook)",
    round(moran_rook$estimate[1], 4),
    round(moran_rook$p.value, 4)
  )
)
## Moran (Rook)              0.2206       0.006
cat(
  sprintf(
    "%-25s %-12s %-12s\n",
    "Moran (Jarak)",
    round(moran_jarak$estimate[1], 4),
    round(moran_jarak$p.value, 4)
  )
)
## Moran (Jarak)             0.0507       0.055
cat(
  sprintf(
    "%-25s %-12s %-12s\n",
    "Moran (KNN)",
    round(moran_knn$estimate[1], 4),
    round(moran_knn$p.value, 4)
  )
)
## Moran (KNN)               0.1886       0.0069
cat(
  sprintf(
    "%-25s %-12s %-12s\n",
    "Geary (Queen)",
    round(geary_queen$estimate[1], 4),
    round(geary_queen$p.value, 4)
  )
)
## Geary (Queen)             0.7408       0.0065
cat(
  sprintf(
    "%-25s %-12s %-12s\n",
    "Geary (Rook)",
    round(geary_rook$estimate[1], 4),
    round(geary_rook$p.value, 4)
  )
)
## Geary (Rook)              0.7475       0.0082
cat(
  sprintf(
    "%-25s %-12s %-12s\n",
    "Getis-Ord G (Queen)",
    round(go_queen$estimate[1], 4),
    round(go_queen$p.value, 4)
  )
)
## Getis-Ord G (Queen)       0.1355       0.1995
cat("====================================================\n")
## ====================================================
cat("LISA      : lihat peta kategori cluster lokal\n")
## LISA      : lihat peta kategori cluster lokal
cat("G* Lokal  : lihat peta hot spot dan cold spot\n")
## G* Lokal  : lihat peta hot spot dan cold spot
cat("====================================================\n")
## ====================================================
# ==============================================================================
# BAB 5 - KRIGING
# ==============================================================================

cat("\n====================================================\n")
## 
## ====================================================
cat("BAB 5 - KRIGING\n")
## BAB 5 - KRIGING
cat("====================================================\n")
## ====================================================
# Konversi spatial
coordinates(curahhujan) <- ~ LON + LAT

proj4string(curahhujan) <- CRS(
  "+proj=longlat +datum=WGS84"
)

# Plot titik curah hujan
spplot(
  curahhujan,
  "curah_hujan_tahunan",
  main = "Curah Hujan NASA POWER 2023",
  col.regions = heat.colors(100)
)

# Histogram
hist(
  curahhujan$curah_hujan_tahunan,
  main = "Distribusi Curah Hujan",
  xlab = "Curah Hujan (mm)",
  col = "skyblue",
  breaks = 10
)

# Statistik deskriptif
summary(curahhujan$curah_hujan_tahunan)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1145    1589    1803    1773    1988    2153
# Shapiro test
shapiro.test(
  curahhujan$curah_hujan_tahunan
)
## 
##  Shapiro-Wilk normality test
## 
## data:  curahhujan$curah_hujan_tahunan
## W = 0.96146, p-value = 0.3374
# Variogram empiris
# Variogram menggambarkan bagaimana kemiripan nilai berubah seiring jarak
# Ini adalah langkah KUNCI dalam Kriging
vgm_empiris <- variogram(
  curah_hujan_tahunan ~ 1,
  data = curahhujan,
  cutoff = 150,
  width = 10
)

print(vgm_empiris)
##   np      dist    gamma dir.hor dir.ver   id
## 1 25  55.29551 77412.93       0       0 var1
## 2 24  69.01449 11501.81       0       0 var1
## 3 40  88.43538 83376.70       0       0 var1
## 4 20 110.59099 48906.98       0       0 var1
## 5 50 133.12074 39832.18       0       0 var1
## 6 30 148.69657 80599.19       0       0 var1
plot(
  vgm_empiris,
  main = "Variogram Empiris",
  xlab = "Jarak (Km)",
  ylab = "Semivariance",
  pch = 19,
  col = "blue"
)

#lihat outlier
# 1. Cek rentang nilai koordinat asli data Anda
bbox(curahhujan)
##        min    max
## LON 108.75 111.25
## LAT  -8.50  -6.00
# Baca variogram: perhatikan 3 parameter penting
# - Nugget (c0)   : nilai semivariance saat jarak = 0 (variabilitas mikro)
# - Sill (c0+c)   : nilai semivariance saat sudah konstan (plateau)
# - Range (a)     : jarak di mana variogram mencapai sill

# FITTING MODEL VARIOGRAM
# Parameter awal
nugget_awal <- min(vgm_empiris$gamma)

sill_awal <- max(vgm_empiris$gamma)

range_awal <- vgm_empiris$dist[
  which.max(vgm_empiris$gamma)
] / 2

# Model spherical
model_sph <- fit.variogram(
  vgm_empiris,
  model = vgm(
    psill = sill_awal,
    model = "Sph",
    range = range_awal,
    nugget = nugget_awal
  )
)

# Model exponential
model_exp <- fit.variogram(
  vgm_empiris,
  model = vgm(
    psill = sill_awal,
    model = "Exp",
    range = range_awal,
    nugget = nugget_awal
  )
)

# Model gaussian
model_gau <- fit.variogram(
  vgm_empiris,
  model = vgm(
    psill = sill_awal,
    model = "Gau",
    range = range_awal,
    nugget = nugget_awal
  )
)

cat("\n===== MODEL VARIOGRAM =====\n")
## 
## ===== MODEL VARIOGRAM =====
print(model_sph)
##   model    psill    range
## 1   Nug 11501.81  0.00000
## 2   Sph 83376.70 44.21769
print(model_exp)
##   model     psill   range
## 1   Nug  64980.25    0.00
## 2   Exp 173285.98 1066.24
print(model_gau)
##   model     psill    range
## 1   Nug  80008.67   0.0000
## 2   Gau 197618.44 854.5296
# SSE
sse_sph <- attr(model_sph, "SSErr")
sse_exp <- attr(model_exp, "SSErr")
sse_gau <- attr(model_gau, "SSErr")

cat("\n===== SSE =====\n")
## 
## ===== SSE =====
cat("SSE Spherical :", sse_sph, "\n")
## SSE Spherical : 50481168
cat("SSE Exponential :", sse_exp, "\n")
## SSE Exponential : 28777142
cat("SSE Gaussian :", sse_gau, "\n")
## SSE Gaussian : 32310787
cat("Model Terbaik   : model dengan SSE terkecil\n")
## Model Terbaik   : model dengan SSE terkecil
# Model terbaik
model_terbaik <- model_sph

if (sse_exp < sse_sph &
    sse_exp < sse_gau) {
  model_terbaik <- model_exp
}

if (sse_gau < sse_sph &
    sse_gau < sse_exp) {
  model_terbaik <- model_gau
}

# Plot variogram empiris + model terbaik
plot(vgm_empiris, model_terbaik,
     main = "Variogram Empiris vs Model Terpilih",
     xlab = "Jarak (km)",
     ylab = "Semivariance")

library(gstat)

# 1. Mengunci parameter kecocokan secara manual menggunakan fit.method = 1 atau 6
# Kita ganti taksiran awalnya agar pas dengan sebaran titik di grafik Anda
taksiran_baru <- vgm(psill = 60000, model = "Exp", range = 70, nugget = 20000)

# 2. Lakukan fitting ulang dengan metode penyeimbang bobot jarak
model_perbaikan <- fit.variogram(vgm_empiris, model = taksiran_baru, fit.method = 6)

# 3. Cetak parameter baru untuk melihat apakah range sudah realistis (< 150 km)
print(model_perbaikan)
##   model     psill    range
## 1   Nug  45401.12   0.0000
## 2   Exp 198444.96 979.1348
# 4. Tampilkan plot hasil perbaikan
plot(vgm_empiris, model = model_perbaikan,
     main = "Variogram Hasil Perbaikan Parameter",
     xlab = "Jarak (km)",
     ylab = "Semivariance",
     col  = "blue",
     pch  = 19)

# Grid prediksi
shp_jateng_sp <- as(
  shp_gabung,
  "Spatial"
)

grid_jateng <- makegrid(
  shp_jateng_sp,
  cellsize = 0.05
)

colnames(grid_jateng) <- c(
  "LON",
  "LAT"
)

coordinates(grid_jateng) <- ~ LON + LAT

proj4string(grid_jateng) <- CRS(
  "+proj=longlat +datum=WGS84"
)

grid_jateng <- grid_jateng[
  !is.na(
    over(grid_jateng, shp_jateng_sp)[,1]
  ),
]

# Kriging
hasil_kriging <- krige(
  formula = curah_hujan_tahunan ~ 1,
  locations = curahhujan,
  newdata = grid_jateng,
  model = model_terbaik
)
## [using ordinary kriging]
summary(hasil_kriging)
## Object of class SpatialPointsDataFrame
## Coordinates:
##         min     max
## LON 108.600 111.650
## LAT  -8.187  -5.837
## Is projected: FALSE 
## proj4string : [+proj=longlat +datum=WGS84 +no_defs]
## Number of points: 1125
## Data attributes:
##    var1.pred       var1.var    
##  Min.   :1705   Min.   :76697  
##  1st Qu.:1774   1st Qu.:77549  
##  Median :1826   Median :77883  
##  Mean   :1825   Mean   :78498  
##  3rd Qu.:1874   3rd Qu.:78904  
##  Max.   :1931   Max.   :87463
# Data frame hasil
kriging_df <- as.data.frame(
  hasil_kriging
)

colnames(kriging_df) <- c(
  "LON",
  "LAT",
  "prediksi",
  "varians"
)

# Peta prediksi
ggplot() +
  geom_tile(
    data = kriging_df,
    aes(
      x = LON,
      y = LAT,
      fill = prediksi
    )
  ) +
  geom_sf(
    data = shp_gabung,
    fill = NA,
    color = "white",
    size = 0.4
  ) +
  scale_fill_viridis_c(
    name = "CH (mm)",
    option = "turbo"
  ) +
  labs(
    title = "Prediksi Curah Hujan Jawa Tengah 2023",
    subtitle = paste(
      "Model:",
      model_terbaik$model[2]
    ),
    x = "Longitude",
    y = "Latitude"
  ) +
  theme_minimal()

# Peta varians
ggplot() +
  geom_tile(
    data = kriging_df,
    aes(
      x = LON,
      y = LAT,
      fill = varians
    )
  ) +
  geom_sf(
    data = shp_gabung,
    fill = NA,
    color = "white",
    size = 0.4
  ) +
  scale_fill_viridis_c(
    name = "Varians",
    option = "magma"
  ) +
  labs(
    title = "Varians Prediksi Kriging",
    subtitle = "Semakin gelap = semakin tidak pasti",
    x = "Longitude",
    y = "Latitude"
  ) +
  theme_minimal()

# ==============================================================================
# SELESAI
# ==============================================================================

cat("\n====================================================\n")
## 
## ====================================================
cat("SEMUA ANALISIS SELESAI\n")
## SEMUA ANALISIS SELESAI
cat("====================================================\n")
## ====================================================
cat("File yang dihasilkan:\n")
## File yang dihasilkan:
cat("- jateng_kemiskinan.shp\n")
## - jateng_kemiskinan.shp
cat("- Berbagai visualisasi dan analisis spasial\n")
## - Berbagai visualisasi dan analisis spasial
cat("====================================================\n")
## ====================================================