library(rsconnect)
Pada tugas ini dipilih lima visualisasi dari materi Kuliah 9 yang menurut saya perlu diperbaiki:
| No | Slide | Visualisasi awal | Masalah utama |
|---|---|---|---|
| 1 | 6 | Diagram lingkaran 3D keterisian tempat tidur RS DKI Jakarta | Pie 3D untuk data urutan waktu |
| 2 | 7 | Diagram lingkaran sistem pembayaran | Banyak kategori, selisih sulit dibandingkan, kategori kecil tak terbaca |
| 3 | 8 | Diagram batang vertikal persentase penduduk pengguna komputer per provinsi | Tidak terurut, label sumbu berdempetan dan miring |
| 4 | 30 | Peta tematik tingkat kemiskinan provinsi | Warna pucat, tanpa nilai, legenda tanpa kelas |
| 5 | 29 | Jaringan perdagangan antarnegara ASEAN | Panah tanpa angka, ketebalan seragam, garis bersilangan |
Untuk setiap visualisasi dijelaskan alasan perbaikan, perbaikan yang dilakukan, dan interpretasinya.
Tangkapan layar visualisasi awal bisa diletakkan di folder yang sama dengan file ini dengan nama
sebelum_slide6.png,sebelum_slide7.png,sebelum_slide8.png,sebelum_slide29.png, dansebelum_slide30.png. Jika file tidak ada, bagian gambar akan dilewati.
tt <- data.frame(
tanggal = factor(c("29 Jan", "30 Jan", "31 Jan", "1 Feb"),
levels = c("29 Jan", "30 Jan", "31 Jan", "1 Feb")),
persen = c(54, 57, 57, 60)
)
tt$sorot <- ifelse(tt$tanggal == "1 Feb", "terbaru", "lain")
ggplot(tt, aes(x = tanggal, y = persen, fill = sorot)) +
geom_col(width = 0.6, show.legend = FALSE) +
geom_text(aes(label = paste0(persen, "%")), vjust = -0.5,
fontface = "bold", size = 5) +
scale_fill_manual(values = c(lain = "#9ECAE1", terbaru = "#08519C")) +
scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 20),
labels = function(x) paste0(x, "%"),
expand = c(0, 0)) +
labs(title = "Keterisian tempat tidur RS di DKI Jakarta naik dari 54% menjadi 60%",
subtitle = "Persentase keterisian tempat tidur, 29 Januari - 1 Februari",
x = NULL, y = "Keterisian tempat tidur",
caption = "Sumber: Dinas Kesehatan DKI Jakarta (data dari slide Kuliah 9)") +
theme_minimal(base_size = 13) +
theme(panel.grid.major.x = element_blank(),
panel.grid.minor = element_blank(),
plot.title = element_text(face = "bold", size = 13),
plot.title.position = "plot")
Keterisian tempat tidur rumah sakit di DKI Jakarta cenderung meningkat selama empat hari pengamatan, yaitu dari 54% pada 29 Januari menjadi 57% pada 30 dan 31 Januari, lalu 60% pada 1 Februari. Kenaikan total sebesar 6 poin persentase dalam empat hari. Pada 30 dan 31 Januari keterisian sama (57%), sehingga kenaikan tidak terjadi setiap hari. Pada 1 Februari sekitar enam dari sepuluh tempat tidur sudah terisi, dan masih ada sekitar 40% kapasitas tersisa. Karena hanya ada empat titik waktu, hasil ini menggambarkan tren jangka pendek dan belum cukup untuk menyimpulkan pola jangka panjang.
bayar <- data.frame(
metode = c("M-Banking", "COD", "Paylater/Cicilan", "Lainnya"),
persen = c(64, 20, 2, 14)
)
# urutan: terbesar di atas, "Lainnya" paling bawah
urut <- c("Lainnya", "Paylater/Cicilan", "COD", "M-Banking")
bayar$metode <- factor(bayar$metode, levels = urut)
bayar$sorot <- ifelse(bayar$metode == "M-Banking", "utama", "lain")
ggplot(bayar, aes(x = persen, y = metode, fill = sorot)) +
geom_col(width = 0.65, show.legend = FALSE) +
geom_text(aes(label = paste0(persen, "%")), hjust = -0.2,
fontface = "bold", size = 5) +
scale_fill_manual(values = c(lain = "grey70", utama = "#E6550D")) +
scale_x_continuous(limits = c(0, 75), expand = c(0, 0)) +
labs(title = "Mayoritas pelanggan (64%) memilih M-Banking sebagai metode pembayaran",
subtitle = "Persentase pelanggan menurut sistem pembayaran",
x = NULL, y = NULL,
caption = "Sumber: data pada slide Kuliah 9") +
theme_minimal(base_size = 13) +
theme(panel.grid = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_text(size = 12),
plot.title = element_text(face = "bold", size = 13),
plot.title.position = "plot")
M-Banking adalah metode pembayaran yang paling banyak dipilih, yaitu 64% pelanggan, atau lebih dari tiga kali lipat COD yang berada di posisi kedua (20%). Kategori “Lainnya” menyumbang 14%, sedangkan Paylater/Cicilan hanya 2%. Dua metode teratas (M-Banking dan COD) bersama-sama mencakup 84% pelanggan. Pada bentuk diagram batang, selisih antarkategori terbaca langsung dari panjang batang, sehingga dominasi M-Banking dan kecilnya porsi Paylater/Cicilan lebih jelas dibanding versi diagram lingkaran.
komputer <- data.frame(
provinsi = c("Aceh", "Sumatera Utara", "Sumatera Barat", "Riau", "Jambi",
"Sumatera Selatan", "Bengkulu", "Lampung",
"Kep. Bangka Belitung", "Kep. Riau", "DKI Jakarta",
"Jawa Barat", "Jawa Tengah", "DI Yogyakarta", "Jawa Timur",
"Banten", "Bali", "Nusa Tenggara Barat", "Nusa Tenggara Timur",
"Kalimantan Barat", "Kalimantan Tengah", "Kalimantan Selatan",
"Kalimantan Timur", "Kalimantan Utara", "Sulawesi Utara",
"Sulawesi Tengah", "Sulawesi Selatan", "Sulawesi Tenggara",
"Gorontalo", "Sulawesi Barat", "Maluku", "Maluku Utara",
"Papua Barat", "Papua"),
persen = c(11.64, 14.17, 17.0, 14.5, 12.2, 11.1, 14.89, 9.94, 12.01, 20.72,
23.51, 14.52, 13.17, 23.35, 14.22, 15.27, 18.62, 12.03, 11.39,
10.45, 13.58, 17.35, 19.42, 18.02, 14.27, 13.61, 15.41, 15.8,
16.46, 12.3, 13.78, 11.26, 14.04, 8.2)
)
stopifnot(nrow(komputer) == 34, length(komputer$persen) == 34)
rata <- mean(komputer$persen)
komputer <- komputer %>%
mutate(kategori = ifelse(persen >= rata, "Di atas rata-rata",
"Di bawah rata-rata"),
provinsi = reorder(provinsi, persen))
ggplot(komputer, aes(x = persen, y = provinsi, color = kategori)) +
geom_segment(aes(x = 0, xend = persen, y = provinsi, yend = provinsi),
linewidth = 0.6) +
geom_point(size = 2.8) +
geom_text(aes(label = sprintf("%.1f", persen)), hjust = -0.6, size = 3,
show.legend = FALSE) +
geom_vline(xintercept = rata, linetype = "dashed", color = "grey40") +
annotate("text", x = rata, y = 1.2,
label = paste0("Rata-rata: ", round(rata, 1), "%"),
hjust = -0.1, size = 3.3, color = "grey30") +
scale_color_manual(values = c("Di atas rata-rata" = "#08519C",
"Di bawah rata-rata" = "#BDBDBD")) +
scale_x_continuous(limits = c(0, 27), expand = c(0, 0)) +
labs(title = "DKI Jakarta dan DI Yogyakarta tertinggi dalam penggunaan komputer",
subtitle = "Persentase penduduk yang menggunakan komputer menurut provinsi, 2019",
x = "Persentase penduduk (%)", y = NULL, color = NULL,
caption = "Sumber: bps.go.id, Situasi Tahun 2019") +
theme_minimal(base_size = 11) +
theme(panel.grid.major.y = element_blank(),
panel.grid.minor = element_blank(),
legend.position = "top",
legend.justification = "left",
plot.title = element_text(face = "bold"),
plot.title.position = "plot")
Persentase penduduk yang menggunakan komputer di Indonesia pada 2019 masih rendah dan tidak merata. Rata-rata antarprovinsi hanya sekitar 14.7%. Provinsi tertinggi adalah DKI Jakarta (23.51%), diikuti DI Yogyakarta (23.35%) dan Kep. Riau (20.72%). Provinsi terendah adalah Papua (8.2%), diikuti Lampung dan Kalimantan Barat. Jarak antara provinsi tertinggi dan terendah sekitar 15.3 poin persentase, atau hampir tiga kali lipat. Provinsi yang berada di atas rata-rata (13 provinsi) didominasi wilayah dengan pusat ekonomi dan pendidikan yang kuat, sedangkan sebagian besar provinsi lain berkumpul pada kisaran 11-15%. Perlu dicatat bahwa urutan ini adalah persentase, bukan jumlah penduduk, sehingga provinsi berpenduduk besar seperti Jawa Barat tidak otomatis berada di peringkat atas.
Data yang perlu disiapkan (taruh di folder yang sama dengan file ini):
kemiskinan_2020.csvdengan kolomprovinsidanpersen(persentase penduduk miskin per provinsi, dari BPS, sesuaikan periodenya dengan slide). Template ada dikemiskinan_2020_template.csv: isi kolompersen, lalu ganti nama file menjadikemiskinan_2020.csv.Batas wilayah provinsi: jika ada file
indonesia_provinsi.geojsondi folder ini, file itu yang dipakai. Jika tidak ada, kode mencari filegadm41_IDN_1.shp(hasil unduhan GADM) di folder ini dan subfoldernya. Jika itu pun tidak ada, kode mengunduh dari GADM secara otomatis (butuh internet).Paket yang dibutuhkan:
install.packages(c("sf", "patchwork", "geodata")).Jika
kemiskinan_2020.csvbelum lengkap, bagian ini otomatis dilewati saat Knit dan muncul catatan peringatan.
library(sf)
library(patchwork)
library(dplyr)
# 1. Baca data CSV kemiskinan
miskin <- read.csv("D:\\IPB Kuliah\\Semester 3\\Eksplorasi dan Visualisasi Data Besar\\Praktikum\\Pertemuan 8 UAS\\kemiskinan_2020.csv", stringsAsFactors = FALSE)
# 2. Cari file shapefile GADM secara otomatis di folder proyek
shp_gadm <- list.files(".", pattern = "gadm41_IDN_1\\.shp$",
recursive = TRUE, full.names = TRUE)
# 3. WAJIB ADA: Masukkan path file shp ke dalam objek 'peta'
# Langsung arahkan ke file .shp Anda secara spesifik
peta <- st_read("D:\\IPB Kuliah\\Semester 3\\Eksplorasi dan Visualisasi Data Besar\\Praktikum\\Pertemuan 8 UAS\\gadm41_IDN_shp-20260928T053213Z-1-001\\gadm41_IDN_1.shp")
## Reading layer `gadm41_IDN_1' from data source
## `D:\IPB Kuliah\Semester 3\Eksplorasi dan Visualisasi Data Besar\Praktikum\Pertemuan 8 UAS\gadm41_IDN_shp-20260928T053213Z-1-001\gadm41_IDN_1.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 34 features and 11 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 95.00971 ymin: -11.00761 xmax: 141.0194 ymax: 6.076941
## Geodetic CRS: WGS 84
# kolom yang berisi nama provinsi
kandidat <- c("NAME_1", "provinsi", "Provinsi", "PROVINSI", "WADMPR", "state", "name")
kolom_nama <- kandidat[kandidat %in% names(peta)][1]
stopifnot("Kolom nama provinsi pada peta tidak ditemukan, cek names(peta)" = !is.na(kolom_nama))
# samakan penulisan nama provinsi pada data dan peta
norm <- function(x) {
x <- toupper(as.character(x))
x <- gsub("\\.", "", x)
x <- gsub("KEP ", "KEPULAUAN ", x)
x <- gsub("^DKI ", "", x)
x <- gsub("^DI ", "", x)
x <- gsub("DAERAH ISTIMEWA ", "", x)
x <- gsub("[^A-Z]", "", x)
x <- sub("ISLANDS$", "", x)
x <- sub("^JAKARTARAYA$", "JAKARTA", x)
x <- sub("^IRIANJAYABARAT$", "PAPUABARAT", x)
x <- sub("^KEPULAUANBANGKABELITUNG$", "BANGKABELITUNG", x)
x
}
peta$kunci <- norm(peta[[kolom_nama]])
miskin$kunci <- norm(miskin$provinsi)
# cek nama yang tidak cocok antara data dan peta
tak_cocok <- setdiff(miskin$kunci, peta$kunci)
if (length(tak_cocok) > 0) {
message("Nama provinsi di data yang tidak ada di peta: ",
paste(tak_cocok, collapse = ", "),
"\nNama di peta: ", paste(sort(peta$kunci), collapse = ", "))
}
# buang semua kolom atribut peta kecuali kunci (geometri ikut terbawa), supaya tidak
# bentrok nama kolom (mis. peta sudah punya "provinsi" atau "persen" -> jadi persen.x / persen.y)
peta <- peta[, "kunci"]
miskin <- miskin[!duplicated(miskin$kunci), c("kunci", "provinsi", "persen")]
peta <- left_join(peta, miskin, by = "kunci")
peta$persen <- as.numeric(peta$persen)
stopifnot("Tidak ada provinsi yang cocok antara data dan peta, cek pesan nama tak cocok" = sum(!is.na(peta$persen)) > 0)
# kelas kuintil
br <- as.numeric(quantile(peta$persen, probs = seq(0, 1, 0.2), na.rm = TRUE))
br <- round(br, 1)
br[1] <- floor(min(peta$persen, na.rm = TRUE) * 10) / 10
br[length(br)] <- ceiling(max(peta$persen, na.rm = TRUE) * 10) / 10
br <- unique(br)
peta$kelas <- cut(peta$persen, breaks = br, include.lowest = TRUE, dig.lab = 3)
# label 5 tertinggi dan 5 terendah
urut <- peta %>% filter(!is.na(persen)) %>% arrange(desc(persen))
sorot <- bind_rows(head(urut, 5), tail(urut, 5))
titik <- suppressWarnings(st_point_on_surface(sorot))
titik$label <- paste0(titik$provinsi, "\n", titik$persen, "%")
p_peta <- ggplot(peta) +
geom_sf(aes(fill = kelas), color = "white", linewidth = 0.2) +
geom_sf_text(data = titik, aes(label = label), size = 2.6,
fontface = "bold", check_overlap = TRUE) +
scale_fill_brewer(palette = "YlOrRd", na.value = "grey85",
name = "Penduduk miskin (%)") +
labs(title = "Peta tingkat kemiskinan provinsi") +
theme_void(base_size = 11) +
theme(legend.position = "bottom",
plot.title = element_text(face = "bold"))
p_bar <- peta %>%
st_drop_geometry() %>%
filter(!is.na(persen)) %>%
mutate(provinsi = reorder(provinsi, persen)) %>%
ggplot(aes(x = persen, y = provinsi, fill = kelas)) +
geom_col(show.legend = FALSE) +
scale_fill_brewer(palette = "YlOrRd") +
labs(title = "Peringkat provinsi", x = "Penduduk miskin (%)", y = NULL,
caption = "Sumber: BPS (data diisi dari kemiskinan_2020.csv)") +
theme_minimal(base_size = 9) +
theme(panel.grid.major.y = element_blank(),
plot.title = element_text(face = "bold"))
p_peta + p_bar + plot_layout(widths = c(1.5, 1))
Rata-rata tingkat kemiskinan antarprovinsi sekitar 10.8%. Provinsi tertinggi adalah Papua (26.8%), diikuti Papua Barat (21.7%) dan Nusa Tenggara Timur (21.21%). Provinsi terendah adalah Bali (4.45%), diikuti DKI Jakarta (4.69%) dan Kalimantan Selatan (4.83%). Selisih tertinggi dan terendah sekitar 22.4 poin persentase. Peta menunjukkan sebaran wilayah secara spasial, sedangkan diagram batang di sebelahnya memperlihatkan peringkat dan angka tepat, termasuk provinsi kecil yang sulit terlihat di peta. Perlu dicatat bahwa peta menampilkan persentase penduduk miskin, bukan jumlah orang, sehingga provinsi berpenduduk besar belum tentu memiliki persentase tinggi.
Data yang perlu disiapkan:
perdagangan_asean.csvdengan kolomdari,ke,nilai(nilai perdagangan dari negara asal ke negara tujuan, satu baris per panah). Template ada diperdagangan_asean_template.csv: isi kolomnilaidengan data asli (misalnya dari ASEANstats atau UN Comtrade), hapus baris pasangan yang tidak dipakai, lalu ganti nama file menjadiperdagangan_asean.csv. Angka tidak saya isi karena slide asli tidak mencantumkannya. Paket yang dibutuhkan:install.packages(c("igraph", "ggraph")).
CATATAN: perdagangan_asean.csv belum ada atau
kolom nilai masih kosong, bagian ini dilewati. Lengkapi
datanya lalu Knit ulang.
library(visNetwork)
library(readxl)
edges <- read_excel("perdagangan_asean.xlsx", sheet = "Data Perdagangan")
names(edges) <- c("dari", "ke", "nilai")
edges$nilai <- as.numeric(edges$nilai)
edges <- edges[edges$dari != edges$ke, ]
edges$terkait <- ifelse(edges$dari == "Indonesia" | edges$ke == "Indonesia",
"Melibatkan Indonesia", "Antarnegara lain")
fmt <- function(x) format(round(x, 1), big.mark = ".", decimal.mark = ",", trim = TRUE)
satuan <- "juta USD"
negara <- unique(c(edges$dari, edges$ke))
total <- sapply(negara, function(n) sum(edges$nilai[edges$dari == n | edges$ke == n]))
mitra_ri <- unique(c(edges$dari[edges$ke == "Indonesia"], edges$ke[edges$dari == "Indonesia"]))
nodes <- data.frame(
id = negara,
label = negara,
value = as.numeric(total),
color = ifelse(negara == "Indonesia", "#FF7F0E",
ifelse(negara %in% mitra_ri, "#0086B0", "#DDDDDD")),
title = paste0(negara, "<br>Total perdagangan: ", fmt(total), " ", satuan),
stringsAsFactors = FALSE
)
# Menyiapkan kolom untuk visNetwork
edges$from <- edges$dari
edges$to <- edges$ke
edges$width <- log(edges$nilai + 1) * 0.8
edges$title <- paste0(edges$dari, " -> ", edges$ke, ": ", fmt(edges$nilai), " ", satuan)
edges$arrows <- "to"
# WAJIB: Tampilkan objek visNetwork dengan tinggi yang jelas
visNetwork(nodes, edges, height = "500px", width = "100%") %>%
visNodes(scaling = list(min = 15, max = 40)) %>%
visEdges(smooth = FALSE) %>%
visInteraction(dragNodes = TRUE, hover = TRUE) %>%
visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)
ggplot(edges, aes(x = ke, y = dari, fill = nilai)) +
geom_tile(color = "white") +
geom_text(aes(label = round(nilai, 1)), size = 3.5) +
scale_fill_distiller(palette = "Blues", direction = 1,
name = paste0("Nilai (", satuan, ")")) +
labs(title = "Matriks nilai perdagangan asal-tujuan",
x = "Negara tujuan", y = "Negara asal") +
theme_minimal(base_size = 11) +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid = element_blank(),
plot.title = element_text(face = "bold"))
Kelima perbaikan memakai prinsip yang sama dari materi Kuliah 9: memilih jenis visualisasi yang sesuai dengan tipe data (waktu, komposisi, perbandingan antarkategori), menggunakan unsur posisi dan panjang untuk perbandingan yang akurat dibanding luas atau sudut, menggunakan warna hanya untuk menonjolkan pesan utama, dan mengurangi noise seperti efek 3D, legenda terpisah, dan label berdempetan. Pada peta dan jaringan, nilai dicantumkan langsung dan diberi pendamping yang memuat angka tepat.
sessionInfo()
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=English_United States.utf8
## [2] LC_CTYPE=English_United States.utf8
## [3] LC_MONETARY=English_United States.utf8
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United States.utf8
##
## time zone: Asia/Bangkok
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] readxl_1.4.5 visNetwork_2.1.4 patchwork_1.3.2 sf_1.1-2
## [5] scales_1.4.0 dplyr_1.2.1 ggplot2_4.0.3 rsconnect_1.5.1
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 jsonlite_2.0.0 compiler_4.5.1 Rcpp_1.1.0
## [5] tidyselect_1.2.1 jquerylib_0.1.4 yaml_2.3.10 fastmap_1.2.0
## [9] R6_2.6.1 labeling_0.4.3 generics_0.1.4 classInt_0.4-11
## [13] knitr_1.50 htmlwidgets_1.6.4 tibble_3.3.0 units_0.8-7
## [17] DBI_1.2.3 bslib_0.9.0 pillar_1.11.0 RColorBrewer_1.1-3
## [21] rlang_1.3.0 cachem_1.1.0 xfun_0.52 sass_0.4.10
## [25] S7_0.2.0 cli_3.6.5 withr_3.0.3 magrittr_2.0.3
## [29] class_7.3-23 digest_0.6.37 grid_4.5.1 rstudioapi_0.17.1
## [33] lifecycle_1.0.5 vctrs_0.7.3 KernSmooth_2.23-26 proxy_0.4-27
## [37] evaluate_1.0.4 glue_1.8.1 cellranger_1.1.0 farver_2.1.2
## [41] e1071_1.7-17 rmarkdown_2.29 tools_4.5.1 pkgconfig_2.0.3
## [45] htmltools_0.5.8.1