Ekonomi Jatim

LIBRARY

library(readxl)
library(dplyr)
library(ggplot2)
library(sf)
library(GGally)
library(ggspatial)
library(viridis)
library(patchwork)
library(scales)

LOAD DATA

data_ekonomi <- read_xlsx(
  "D:/2026 Lebih Baik/SEMESTER 6/Statistik Spasial/Projek/Data Ekonomi Jatim.xlsx",
  sheet = 1
)

# Rename kolom
colnames(data_ekonomi) <- c("kabkot", "TPT", "Kemiskinan", "IPM", "PDRB")

# Cek struktur data
str(data_ekonomi)
## tibble [38 × 5] (S3: tbl_df/tbl/data.frame)
##  $ kabkot    : chr [1:38] "Kabupaten Pacitan" "Kabupaten Ponorogo" "Kabupaten Trenggalek" "Kabupaten Tulungagung" ...
##  $ TPT       : num [1:38] 1.4 3.85 3.86 4.03 4.49 4.71 5 3.08 3.07 3.94 ...
##  $ Kemiskinan: num [1:38] 72.5 77.9 72.3 63.2 89 ...
##  $ IPM       : num [1:38] 72.3 74.7 73.4 75.9 74.4 ...
##  $ PDRB      : num [1:38] 38215 30007 35110 49485 40200 ...
head(data_ekonomi)
## # A tibble: 6 × 5
##   kabkot                  TPT Kemiskinan   IPM  PDRB
##   <chr>                 <dbl>      <dbl> <dbl> <dbl>
## 1 Kabupaten Pacitan      1.4        72.5  72.3 38215
## 2 Kabupaten Ponorogo     3.85       77.9  74.6 30007
## 3 Kabupaten Trenggalek   3.86       72.4  73.4 35110
## 4 Kabupaten Tulungagung  4.03       63.2  75.9 49485
## 5 Kabupaten Blitar       4.49       89.0  74.4 40200
## 6 Kabupaten Kediri       4.71      157.   76.1 34496
# Statistik deskriptif
summary(data_ekonomi[, c("TPT", "Kemiskinan", "IPM", "PDRB")])
##       TPT          Kemiskinan          IPM             PDRB       
##  Min.   :1.330   Min.   :  6.22   Min.   :67.23   Min.   : 25531  
##  1st Qu.:3.115   1st Qu.: 65.28   1st Qu.:72.45   1st Qu.: 36641  
##  Median :3.855   Median :101.40   Median :75.32   Median : 42358  
##  Mean   :3.780   Mean   :102.00   Mean   :76.06   Mean   : 79425  
##  3rd Qu.:4.565   3rd Qu.:143.31   3rd Qu.:79.27   3rd Qu.: 77958  
##  Max.   :5.750   Max.   :235.63   Max.   :85.65   Max.   :581558

LOAD SHAPEFILE PETA JAWA TIMUR

# Baca file GeoJSON (pastikan sudah di-unzip dulu)
IDN <- st_read(
  "D:/2026 Lebih Baik/SEMESTER 6/Statistik Spasial/Projek/gadm41_IDN_2.json/gadm41_IDN_2.json"
)
## Reading layer `gadm41_IDN_2' from data source 
##   `D:\2026 Lebih Baik\SEMESTER 6\Statistik Spasial\Projek\gadm41_IDN_2.json\gadm41_IDN_2.json' 
##   using driver `GeoJSON'
## Simple feature collection with 502 features and 13 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: 95.0102 ymin: -11.0075 xmax: 141.0194 ymax: 6.0766
## Geodetic CRS:  WGS 84
# Cek nama provinsi yang tersedia di kolom NAME_1
# Jalankan baris ini untuk tahu nama persis Jawa Timur di shapefile
unique(IDN$NAME_1)
##  [1] "Aceh"              "Bali"              "BangkaBelitung"   
##  [4] "Banten"            "Bengkulu"          "Gorontalo"        
##  [7] "JakartaRaya"       "Jambi"             "JawaBarat"        
## [10] "JawaTengah"        "JawaTimur"         "KalimantanBarat"  
## [13] "KalimantanSelatan" "KalimantanTengah"  "KalimantanTimur"  
## [16] "KalimantanUtara"   "KepulauanRiau"     "Lampung"          
## [19] "Maluku"            "MalukuUtara"       "NusaTenggaraBarat"
## [22] "NusaTenggaraTimur" "Papua"             "PapuaBarat"       
## [25] "Riau"              "SulawesiBarat"     "SulawesiSelatan"  
## [28] "SulawesiTengah"    "SulawesiTenggara"  "SulawesiUtara"    
## [31] "SumateraBarat"     "SumateraSelatan"   "SumateraUtara"    
## [34] "Yogyakarta"
jatim <- IDN[IDN$NAME_1 == "JawaTimur", ]

# Cek jumlah wilayah (harus 38)
nrow(jatim)
## [1] 38
# Cek nama kabupaten/kota di shapefile
sort(jatim$NAME_2)
##  [1] "Bangkalan"       "Banyuwangi"      "Batu"            "Blitar"         
##  [5] "Bojonegoro"      "Bondowoso"       "Gresik"          "Jember"         
##  [9] "Jombang"         "Kediri"          "KotaBlitar"      "KotaKediri"     
## [13] "KotaMadiun"      "KotaMalang"      "KotaMojokerto"   "KotaPasuruan"   
## [17] "KotaProbolinggo" "Lamongan"        "Lumajang"        "Madiun"         
## [21] "Magetan"         "Malang"          "Mojokerto"       "Nganjuk"        
## [25] "Ngawi"           "Pacitan"         "Pamekasan"       "Pasuruan"       
## [29] "Ponorogo"        "Probolinggo"     "Sampang"         "Sidoarjo"       
## [33] "Situbondo"       "Sumenep"         "Surabaya"        "Trenggalek"     
## [37] "Tuban"           "Tulungagung"

MENYESUAIKAN NAMA KABUPATEN/KOTA

# PERBAIKAN: gsub("Kota ", "Kota ") dipertahankan dengan spasi
# Kota tetap "Kota Kediri" bukan "KotaKediri"
data_ekonomi <- data_ekonomi %>%
  mutate(NAME_2 = kabkot) %>%
  # Hapus prefix "Kabupaten " saja
  mutate(NAME_2 = gsub("^Kabupaten ", "", NAME_2)) %>%
  # "Kota X" dipertahankan apa adanya (tidak dihapus spasinya)
  mutate(NAME_2 = trimws(NAME_2))

# Cek hasil cleaning
data_ekonomi %>% select(kabkot, NAME_2)
## # A tibble: 38 × 2
##    kabkot                NAME_2     
##    <chr>                 <chr>      
##  1 Kabupaten Pacitan     Pacitan    
##  2 Kabupaten Ponorogo    Ponorogo   
##  3 Kabupaten Trenggalek  Trenggalek 
##  4 Kabupaten Tulungagung Tulungagung
##  5 Kabupaten Blitar      Blitar     
##  6 Kabupaten Kediri      Kediri     
##  7 Kabupaten Malang      Malang     
##  8 Kabupaten Lumajang    Lumajang   
##  9 Kabupaten Jember      Jember     
## 10 Kabupaten Banyuwangi  Banyuwangi 
## # ℹ 28 more rows
# Bersihkan nama di shapefile juga
jatim <- jatim %>%
  mutate(NAME_2_clean = trimws(NAME_2))

data_ekonomi <- data_ekonomi %>%
  mutate(NAME_2 = kabkot) %>%
  mutate(NAME_2 = gsub("^Kabupaten ", "", NAME_2)) %>%
  mutate(NAME_2 = gsub("^Kota ", "Kota", NAME_2)) %>%
  mutate(NAME_2 = trimws(NAME_2)) %>%
  mutate(NAME_2 = case_when(
    NAME_2 == "KotaSurabaya" ~ "Surabaya",
    NAME_2 == "KotaBatu" ~ "Batu",
    TRUE ~ NAME_2
  ))
jatim_df <- jatim %>%
  left_join(data_ekonomi, by = c("NAME_2_clean" = "NAME_2"))
sum(is.na(jatim_df$IPM))
## [1] 0
setdiff(data_ekonomi$NAME_2, jatim$NAME_2_clean)
## character(0)

HITUNG TITIK TENGAH UNTUK LABEL

# HITUNG TITIK TENGAH UNTUK LABEL (FIX GRESIK & SUMENEP)

jatim_df <- st_make_valid(jatim_df)

centroids <- jatim_df %>%
  st_cast("POLYGON") %>%                 # pecah multipolygon
  group_by(NAME_2_clean) %>%
  slice_max(st_area(geometry), n = 1) %>%  # ambil pulau terbesar
  ungroup() %>%
  st_point_on_surface() %>%
  mutate(
    long = st_coordinates(.)[, 1],
    lat  = st_coordinates(.)[, 2]
  )

# Cek hasil
nrow(centroids)       
## [1] 38
sum(is.na(centroids$long)) 
## [1] 0
sum(is.na(centroids$lat))  
## [1] 0

CHOROPLETH MAP - IPM

peta_IPM <- ggplot() +
  geom_sf(data = jatim_df, aes(fill = IPM), color = "white", linewidth = 0.3) +
  geom_text(data = centroids,
            aes(x = long, y = lat, label = NAME_2_clean),
            size = 1.8, color = "black") +
  scale_fill_gradient(low = "#fff7ed", high = "#ea580c",
                      name = "IPM", na.value = "grey80") +
  annotation_north_arrow(location = "tr", which_north = "true",
                         style = north_arrow_fancy_orienteering) +
  annotation_scale(location = "bl", width_hint = 0.3) +
  labs(
    title = "Indeks Pembangunan Manusia (IPM)",
    subtitle = "Kabupaten/Kota di Jawa Timur Tahun 2025",
    caption = "Sumber: BPS Jawa Timur, 2025"
  ) +
  theme_minimal() +
  theme(
    plot.title    = element_text(hjust = 0.5, face = "bold", size = 11),
    plot.subtitle = element_text(hjust = 0.5, size = 9),
    axis.text     = element_blank(),
    axis.ticks    = element_blank(),
    panel.grid    = element_blank()
  )

print(peta_IPM)

CHOROPLETH MAP - KEMISKINAN

peta_Kemiskinan <- ggplot() +
  geom_sf(data = jatim_df, aes(fill = Kemiskinan), color = "white", linewidth = 0.3) +
  geom_text(data = centroids,
            aes(x = long, y = lat, label = NAME_2_clean),
            size = 1.8, color = "black") +
  scale_fill_gradient(low = "#ccf5ff", high = "#00b8e6",
                      name = "Ribu Jiwa", na.value = "grey80") +
  annotation_north_arrow(location = "tr", which_north = "true",
                         style = north_arrow_fancy_orienteering) +
  annotation_scale(location = "bl", width_hint = 0.3) +
  labs(
    title = "Jumlah Penduduk Miskin",
    subtitle = "Kabupaten/Kota di Jawa Timur Tahun 2024",
    caption = "Sumber: BPS Jawa Timur, 2024"
  ) +
  theme_minimal() +
  theme(
    plot.title    = element_text(hjust = 0.5, face = "bold", size = 11),
    plot.subtitle = element_text(hjust = 0.5, size = 9),
    axis.text     = element_blank(),
    axis.ticks    = element_blank(),
    panel.grid    = element_blank()
  )

print(peta_Kemiskinan)

CHOROPLETH MAP - TPT

peta_TPT <- ggplot() +
  geom_sf(data = jatim_df, aes(fill = TPT), color = "white", linewidth = 0.3) +
  geom_text(data = centroids,
            aes(x = long, y = lat, label = NAME_2_clean),
            size = 1.8, color = "black") +
  scale_fill_gradient(low = "#ffe6f0", high = "#e60073",
                      name = "%", na.value = "grey80") +
  annotation_north_arrow(location = "tr", which_north = "true",
                         style = north_arrow_fancy_orienteering) +
  annotation_scale(location = "bl", width_hint = 0.3) +
  labs(
    title = "Tingkat Pengangguran Terbuka (TPT)",
    subtitle = "Kabupaten/Kota di Jawa Timur Tahun 2024",
    caption = "Sumber: BPS Jawa Timur, 2024"
  ) +
  theme_minimal() +
  theme(
    plot.title    = element_text(hjust = 0.5, face = "bold", size = 11),
    plot.subtitle = element_text(hjust = 0.5, size = 9),
    axis.text     = element_blank(),
    axis.ticks    = element_blank(),
    panel.grid    = element_blank()
  )

print(peta_TPT)

CHOROPLETH MAP - PDRB

peta_PDRB <- ggplot() +
  geom_sf(data = jatim_df, aes(fill = PDRB), color = "white", linewidth = 0.3) +
  geom_text(data = centroids,
            aes(x = long, y = lat, label = NAME_2_clean),
            size = 1.8, color = "black") +
  scale_fill_gradient(low = "#ecfdf5", high = "#059669",
                      name = "Juta Rp",
                      na.value = "grey80",
                      labels = scales::comma) +
  annotation_north_arrow(location = "tr", which_north = "true",
                         style = north_arrow_fancy_orienteering) +
  annotation_scale(location = "bl", width_hint = 0.3) +
  labs(
    title = "PDRB Per Kapita",
    subtitle = "Kabupaten/Kota di Jawa Timur Tahun 2024",
    caption = "Sumber: BPS Jawa Timur, 2024"
  ) +
  theme_minimal() +
  theme(
    plot.title    = element_text(hjust = 0.5, face = "bold", size = 11),
    plot.subtitle = element_text(hjust = 0.5, size = 9),
    axis.text     = element_blank(),
    axis.ticks    = element_blank(),
    panel.grid    = element_blank()
  )

print(peta_PDRB)

PANEL 4 PETA SEKALIGUS

panel_peta <- (peta_IPM | peta_Kemiskinan) / (peta_TPT | peta_PDRB) +
  plot_annotation(
    title   = "Visualisasi Spasial Indikator Ekonomi\nKabupaten/Kota Jawa Timur 2024",
    caption = "Sumber: BPS Provinsi Jawa Timur, 2024",
    theme   = theme(
      plot.title = element_text(hjust = 0.5, face = "bold", size = 13)
    )
  )

print(panel_peta)

PARALLEL COORDINATE PLOT (PCP)

# Data untuk PCP
data_pcp <- data_ekonomi %>%
  select(kabkot, TPT, Kemiskinan, IPM, PDRB) %>%
  mutate(Tipe = ifelse(grepl("^Kota", kabkot), "Kota", "Kabupaten"))

# PCP dengan skala uniminmax 
pcp_plot <- ggparcoord(
  data_pcp,
  columns     = 2:5,       # TPT, Kemiskinan, IPM, PDRB
  groupColumn = 6,          # Tipe (Kota/Kabupaten)
  scale       = "uniminmax",
  showPoints  = TRUE,
  alphaLines  = 0.5,
  title       = "Parallel Coordinate Plot Indikator Ekonomi\nKabupaten/Kota di Jawa Timur Tahun 2025"
) +
  scale_color_manual(
    values = c("Kabupaten" = "#2196F3", "Kota" = "#FF5722"),
    name   = "Tipe Wilayah"
  ) +
  xlab("Indikator") +
  ylab("Nilai Terstandarisasi (uniminmax)") +
  theme_bw() +
  theme(
    plot.title      = element_text(hjust = 0.5, face = "bold", size = 12),
    legend.position = "bottom",
    axis.text.x     = element_text(face = "bold", size = 10)
  )

print(pcp_plot)