library(sf) 
## Linking to GEOS 3.13.1, GDAL 3.11.0, PROJ 9.6.0; sf_use_s2() is TRUE
library(dplyr) 
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2) 
library(tmap) 
library(leaflet) 
library(classInt) 
library(RColorBrewer)
library(htmltools)
geojson_path <- "C:/Users/USER/OneDrive/Dokumen/Kulyah smt 5/Statistika Lingkungan/33.26_kelurahan.geojson"
kel <- st_read(geojson_path, quiet = TRUE)
print(kel)
## Simple feature collection with 285 features and 5 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XYZ
## Bounding box:  xmin: 109.4834 ymin: -7.244428 xmax: 109.7991 ymax: -6.840548
## z_range:       zmin: 0 zmax: 0
## Geodetic CRS:  WGS 84
## First 10 features:
##    kd_propinsi kd_dati2 kd_kecamatan kd_kelurahan     nm_kelurahan
## 1           33       26          015          016            Curug
## 2           33       26          015          012      Karangjompo
## 3           33       26          008          007 Sinangohprendeng
## 4           33       26          008          019      Tanjungsari
## 5           33       26          001          010         Luragung
## 6           33       26          009          016        Ponolawen
## 7           33       26          008          005       Pringsurat
## 8           33       26          006          001        Pungangan
## 9           33       26          011          005  Randumuktiwaren
## 10          33       26          006          009        Randusari
##                          geometry
## 1  MULTIPOLYGON Z (((109.6439 ...
## 2  MULTIPOLYGON Z (((109.6444 ...
## 3  MULTIPOLYGON Z (((109.5915 ...
## 4  MULTIPOLYGON Z (((109.6026 ...
## 5  MULTIPOLYGON Z (((109.5032 ...
## 6  MULTIPOLYGON Z (((109.5209 ...
## 7  MULTIPOLYGON Z (((109.5916 ...
## 8  MULTIPOLYGON Z (((109.6718 ...
## 9  MULTIPOLYGON Z (((109.559 -...
## 10 MULTIPOLYGON Z (((109.7099 ...
cat(sprintf("Jumlah fitur: %d\n", nrow(kel)))
## Jumlah fitur: 285
# tampilkan nama kolom
attrs <- names(kel)
attrs
## [1] "kd_propinsi"  "kd_dati2"     "kd_kecamatan" "kd_kelurahan" "nm_kelurahan"
## [6] "geometry"
# cari kolom numerik (tanpa geometry)
num_cols <- kel %>% st_drop_geometry() %>% select(where(is.numeric)) %>% names()
cat("Kolom numerik yang tersedia:\n")
## Kolom numerik yang tersedia:
print(num_cols)
## character(0)
# jika tidak ada kolom numerik, buat kolom dummy (contoh: luas dalam m2)
if(length(num_cols) == 0){
kel$area_m2 <- as.numeric(st_area(kel))
num_cols <- "area_m2"
cat("Tidak ada kolom numerik: membuat kolom 'area_m2' berdasarkan luas geometris (m^2).\n")
}
## st_as_s2(): dropping Z and/or M coordinate
## Tidak ada kolom numerik: membuat kolom 'area_m2' berdasarkan luas geometris (m^2).
# Pilih kolom numerik terbaik untuk choropleth: gunakan yang memiliki variansi terbesar
if(length(num_cols) >= 1){
variances <- sapply(num_cols, function(cn) var(kel[[cn]], na.rm = TRUE))
target_col <- names(which.max(variances))
cat(sprintf("Kolom terpilih untuk peta tematik: %s\n", target_col))
} else {
stop("Tidak ada kolom numerik dan pembuatan kolom area gagal.")
}
## Kolom terpilih untuk peta tematik: area_m2
nclass <- 5
vals <- kel[[target_col]]
vals_numeric <- as.numeric(vals)
vals_numeric[is.na(vals_numeric)] <- median(vals_numeric, na.rm = TRUE)
ci <- classIntervals(vals_numeric, n = nclass, style = "quantile")
breaks <- as.numeric(ci$brks)
# Gunakan cut untuk label agar tidak error
labs <- levels(cut(vals_numeric, breaks = breaks, include.lowest = TRUE))
kel_fort <- st_transform(kel, 3857)
kel_fort$cat <- cut(as.numeric(kel[[target_col]]), breaks = breaks, include.lowest = TRUE, labels = labs)


ggplot() +
geom_sf(data = kel_fort, aes(fill = cat), color = "grey20", size = 0.2) +
labs(title = paste("Peta Tematik:", target_col), fill = target_col) +
theme_minimal() +
theme(axis.text = element_blank(), axis.ticks = element_blank())

tmap_mode("view")
## ℹ tmap modes "plot" - "view"
## ℹ toggle with `tmap::ttm()`
m_tmap <- tm_shape(kel) +
tm_polygons(col = target_col, style = "quantile", n = nclass, palette = "YlOrRd", title = target_col, alpha = 0.8) +
tm_layout(title = paste("Peta Choropleth -", target_col))
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_polygons()`: instead of `style = "quantile"`, use fill.scale =
## `tm_scale_intervals()`.
## ℹ Migrate the argument(s) 'style', 'n', 'palette' (rename to 'values') to
##   'tm_scale_intervals(<HERE>)'[v3->v4] `tm_polygons()`: use 'fill' for the fill color of polygons/symbols
## (instead of 'col'), and 'col' for the outlines (instead of 'border.col').[v3->v4] `tm_polygons()`: use `fill_alpha` instead of `alpha`.[v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'[v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(title = )`
m_tmap
## [cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "YlOrRd" is named
## "brewer.yl_or_rd"
## Multiple palettes called "yl_or_rd" found: "brewer.yl_or_rd", "matplotlib.yl_or_rd". The first one, "brewer.yl_or_rd", is returned.
library(sf)
library(leaflet)

# 1. Baca geojson
kel <- st_read("C:/Users/USER/OneDrive/Dokumen/Kulyah smt 5/Statistika Lingkungan/33.26_kelurahan.geojson")
## Reading layer `33.26_kelurahan' from data source 
##   `C:\Users\USER\OneDrive\Dokumen\Kulyah smt 5\Statistika Lingkungan\33.26_kelurahan.geojson' 
##   using driver `GeoJSON'
## Simple feature collection with 285 features and 5 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XYZ
## Bounding box:  xmin: 109.4834 ymin: -7.244428 xmax: 109.7991 ymax: -6.840548
## z_range:       zmin: 0 zmax: 0
## Geodetic CRS:  WGS 84
# 2. Pastikan geometry valid + CRS sesuai
kel <- st_make_valid(kel)
kel <- st_transform(kel, crs = 4326)

# 3. Tentukan kolom target
target_col <- "area_m2"
vals_numeric <- kel[[target_col]]

# 4. Definisikan palet warna
pal_leaf <- colorBin(
  palette = "YlOrRd",
  domain = vals_numeric,
  bins = 5,
  na.color = "#808080"
)

# 5. Buat popup
popup_attrs <- names(kel)[1:min(4, ncol(kel))]
popup <- apply(
  st_drop_geometry(kel)[, popup_attrs, drop = FALSE],
  1,
  function(r) paste(
    paste0(popup_attrs, ": ", ifelse(is.na(r), "-", r)),
    collapse = "<br/>"
  )
)

# 6. Plot choropleth
leaflet(kel) %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addPolygons(
    fillColor   = ~pal_leaf(vals_numeric),
    weight      = 0.5,
    opacity     = 1,
    color       = "#444444",
    fillOpacity = 0.8,
    highlight   = highlightOptions(weight = 2, color = "#666", bringToFront = TRUE),
    label       = lapply(popup, HTML)
  ) %>%
  addLegend(
    pal     = pal_leaf,
    values  = vals_numeric,
    title   = "Luas Area (m²)",
    opacity = 1
  )
# Hitung jumlah kelurahan per kecamatan
summary_table <- kel %>%
  st_drop_geometry() %>%
  group_by(kd_kecamatan) %>%
  summarise(jumlah_kelurahan = n()) %>%
  arrange(kd_kecamatan)

summary_table
## # A tibble: 19 × 2
##    kd_kecamatan jumlah_kelurahan
##    <chr>                   <int>
##  1 001                        14
##  2 002                        15
##  3 003                        11
##  4 004                         9
##  5 005                        10
##  6 006                        14
##  7 007                        15
##  8 008                        25
##  9 009                        23
## 10 010                        17
## 11 011                        22
## 12 012                        14
## 13 013                        19
## 14 014                        10
## 15 015                        16
## 16 016                        16
## 17 017                        13
## 18 018                        11
## 19 019                        11