Pendahuluan

Dokumen ini berisi empat visualisasi dari materi kuliah “Menyiapkan Bahan Visualisasi Data” yang menurut saya perlu diperbaiki, yaitu:

No Slide Visualisasi awal Masalah utama
1 6 Diagram lingkaran 3D keterisian tempat tidur RS DKI Jakarta Bukan data proporsi, efek 3D
2 7 Diagram lingkaran sistem pembayaran Warna senada, legenda terpisah, irisan kecil sulit dibaca
3 8 Diagram batang persentase pengguna komputer per provinsi (urutan acak) Sulit dibandingkan, label miring
4 10 Kasus harian baru COVID-19 dunia (batang + rata-rata bergerak) Garis rata-rata 3 hari tidak tampil, hierarki visual lemah
5 31 Peta Presentase Kemiskinan Kontras Warna Rendah, elemen tidak lengkap

Data diambil dari angka yang tertera pada slide masing-masing. Untuk setiap visualisasi, saya tampilkan versi sebelum (direka ulang sesederhana mungkin agar masalahnya terlihat), lalu versi sesudah, disertai alasan perbaikan, perbaikan yang dilakukan, dan interpretasi.


Visualisasi 1: Tingkat Keterisian Tempat Tidur RS di DKI Jakarta (Slide 6)

Visualisasi Awal

Pada slide kuliah,nilai keterisian ditampilkan sebagai irisan diagram lingkaran 3D sebagai berikut:

1. Alasan perbaikan

  • Jenis grafik tidak sesuai dengan datanya. Diagram lingkaran dipakai untuk menunjukkan bagian dari suatu keseluruhan (total 100%). Di sini keempat nilai (54%, 57%, 57%, 60%) adalah persentase keterisian pada hari yang berbeda, dan jika dijumlahkan hasilnya 228%.
  • Data ini adalah deret waktu, sehingga yang ingin dilihat adalah perubahan dari hari ke hari, sementara diagram lingkaran tidak menunjukkan urutan waktu dan arah tren.
  • Efek 3D dan perspektif membuat irisan di bagian depan tampak lebih besar daripada irisan di belakang, padahal nilainya hampir sama.
  • Empat warna mencolok (hijau, biru, kuning, merah) tidak membawa makna, hanya membedakan hari.
  • Selisih antar nilai kecil, sehingga irisan hampir tidak bisa dibedakan secara visual. Pembaca harus mengandalkan angka.

2. Perbaikan yang dilakukan

  • Mengganti diagram lingkaran dengan diagram garis (deret waktu). Posisi sepanjang sumbu vertikal adalah unsur visual yang paling akurat dibaca, dan garis menunjukkan arah tren secara langsung.
  • Menghilangkan efek 3D dan legenda. Tanggal dipindah ke sumbu horizontal sehingga tidak perlu mencocokkan warna.
  • Memakai satu warna saja, karena semua titik adalah ukuran yang sama pada waktu berbeda.
library(ggplot2)

# Data lebih ringkas dengan seq()
data_rs <- data.frame(
  tanggal = seq(as.Date("2026-01-29"), by = "1 day", length.out = 4),
  keterisian = c(54, 57, 57, 60)
)

# Plot
ggplot(data_rs, aes(x = tanggal, y = keterisian)) +
  geom_line(color = "#2471A3", linewidth = 1.2) +
  geom_point(color = "#2471A3", size = 3.5) +
  geom_text(aes(label = paste0(keterisian, "%")), vjust = -1, size = 4.5) +
  scale_y_continuous(
    limits = c(0, 100), breaks = seq(0, 100, 10),
    labels = \(x) paste0(x, "%"), expand = c(0, 2)
  ) +
  scale_x_date(
    date_breaks = "1 day", date_labels = "%d %b", 
    expand = expansion(mult = 0.08)
  ) +
  labs(
    title = "Tren Tingkat Keterisian Tempat Tidur\nRumah Sakit di DKI Jakarta",
    subtitle = "Periode 29 Januari–1 Februari",
    x = "Tanggal", y = "Tingkat keterisian tempat tidur",
    caption = "Sumber: Dinas Kesehatan DKI Jakarta."
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(face = "bold", size = 15, hjust = 0.5),
    plot.subtitle = element_text(size = 11, hjust = 0.5),
    axis.title = element_text(face = "bold"),
    panel.grid.minor = element_blank(),
    panel.grid.major.x = element_blank(),
    plot.caption = element_text(size = 9, hjust = 0)
  )

3. Interpretasi

Tingkat keterisian tempat tidur rumah sakit di DKI Jakarta meningkat dari 54% pada 29 Januari menjadi 60% pada 1 Februari, yaitu kenaikan 6 poin persentase. Kenaikan terjadi pada 30 Januari (57%), bertahan di angka yang sama pada 31 Januari, lalu naik lagi pada 1 Februari. Pada hari terakhir, sekitar 6 dari 10 tempat tidur telah terisi, sehingga kapasitas tersisa semakin sempit jika tren berlanjut. Pengamatan hanya mencakup empat hari sehingga data ini hanya untuk menggambarkan arah perubahan jangka pendek, namun belum cukup untuk menyimpulkan tren jangka panjang.


Visualisasi 2: Sistem Pembayaran (Slide 7)

bayar <- data.frame(
  metode = c("M-Banking", "COD", "Paylater/Cicilan", "Lainnya"),
  persen = c(64, 20, 2, 14)
)
bayar

Visualisasi Awal

bayar_awal <- bayar
bayar_awal$metode <- factor(bayar_awal$metode,
                            levels = c("COD", "M-Banking", "Paylater/Cicilan", "Lainnya"))
bayar_awal <- bayar_awal[order(bayar_awal$metode), ]

ggplot(bayar_awal, aes(x = "", y = persen, fill = metode)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y", start = 0) +
  geom_text(aes(label = paste0(persen, "%")),
            position = position_stack(vjust = 0.5), size = 3.5) +
  scale_fill_manual(values = c("#F9C9B3", "#F4A672", "#E6882B", "#B8651B")) +
  labs(title = "Sebelum: Sistem Pembayaran", fill = NULL) +
  theme_void(base_size = 12) +
  theme(legend.position = "bottom",
        plot.title = element_text(face = "bold", size = 13))

1. Alasan perbaikan

  • Alasan Perbaikan:
  • Skema Warna Senada & Kurang Kontras: Gambar 1 menggunakan gradasi warna oranye-cokelat yang terlalu mirip satu sama lain, sehingga antar-irisan sulit dibedakan secara cepat.
  • Fokus Visual Tidak Tepat: Warna paling gelap pada Gambar 1 justru diberikan kepada kategori Lainnya (14%), yang dapat mengecoh pembaca dari kategori utama yaitu M-Banking (64%).
  • Tata Letak Legenda Kurang Efektif: Legenda di bagian bawah pada Gambar 1 menyulitkan pembaca karena harus bolak-balik mencocokkan warna juring dengan teks di bawahnya.

2. Perbaikan yang dilakukan

  • Penerapan Palet Warna Kontras & Ramah Buta Warna: Gambar 2 menggunakan empat warna yang saling bertolak belakang (biru, oranye, hijau toska, dan abu-abu) sehingga tiap juring dapat dibedakan secara instan dan ramah bagi penderita buta warna.
  • Penegasan Hirarki Visual (Visual Hierarchy): Kategori dominan M-Banking (64%) diberi warna biru tua sebagai pusat perhatian utama, sedangkan kategori Lainnya diberi warna abu-abu netral agar tidak menyita perhatian.
  • Penyempurnaan Legenda & Kontras Teks: Legenda dipindahkan ke sisi kanan secara vertikal lengkap dengan judul “Metode Pembayaran”, serta label persentase di dalam juring dibuat tebal ber-warna putih agar lebih mudah dibaca.
library(ggplot2)
library(dplyr)

# 1. Menyiapkan Data dengan Urutan Faktor Konsisten
df_pembayaran <- data.frame(
  Kategori = factor(c("M-Banking", "COD", "Paylater/Cicilan", "Lainnya"), 
                    levels = c("M-Banking", "COD", "Paylater/Cicilan", "Lainnya")),
  Persentase = c(64, 20, 14, 2)
)

# 2. Plot Pie Chart Rapi Tanpa Label Menembus Garis
ggplot(df_pembayaran, aes(x = 1, y = Persentase, fill = Kategori)) +
  geom_bar(stat = "identity", width = 1, color = "white", linewidth = 1.2) +
  coord_polar(theta = "y", start = 0) +
  scale_fill_manual(values = c(
    "M-Banking"        = "#0072B2", # Biru Gelap
    "COD"              = "#E69F00", # Oranye
    "Paylater/Cicilan" = "#009E73", # Hijau Toska
    "Lainnya"          = "#737373"  # Abu-Abu
  )) +
  geom_text(
    aes(label = paste0(Persentase, "%")),
    position = position_stack(vjust = 0.5),
    color = "white",
    fontface = "bold",
    size = c(4.5, 4.0, 3.8, 2.6) # Ukuran font 2.6 khusus untuk angka 2% agar fit di dalam juring
  ) +
  
  labs(
    title = "Sistem Pembayaran",
    fill = "Metode Pembayaran"
  ) +
  
  theme_void() +
  theme(
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5, margin = margin(b = 6)),
    plot.subtitle = element_text(size = 10, color = "#444444", hjust = 0.5, margin = margin(b = 12)),
    legend.position = "right", # Nama kategori ditampilkan di legenda sebelah kanan
    legend.title = element_text(face = "bold", size = 10),
    legend.text = element_text(size = 9),
    plot.background = element_rect(fill = "#FFFFFF", color = NA),
    plot.margin = margin(10, 10, 10, 10)
  )

3. Interpretasi

Visualisasi sistem pembayaran tersebut menunjukkan bahwa M-Banking merupakan metode pembayaran pilihan terbanyak sebesar 64%. Posisi berikutnya ditempati oleh COD dengan persentase sebesar 20%, disusul oleh Paylater/Cicilan sebesar 14%. Sementara itu, kategori Lainnya merupakan persentase terkecil yaitu sebesar 2%.


Visualisasi 3: Persentase Penduduk Pengguna Komputer per Provinsi (Slide 8)

Sumber data: BPS (bps.go.id)

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)
)

rata2 <- mean(komputer$persen)
n_atas <- sum(komputer$persen >= rata2)
tertinggi <- komputer[which.max(komputer$persen), ]
terendah  <- komputer[which.min(komputer$persen), ]

Visualisasi Awal

Pada slide asli terdapat diagram batang vertikal dengan provinsi disusun mengikuti urutan geografis dari barat ke timur.

ggplot(komputer, aes(x = factor(provinsi, levels = provinsi), y = persen)) +
  geom_col(fill = "#3B7DB0") +
  labs(title = "Sebelum: Persentase Masyarakat yang Menggunakan Komputer di Berbagai Provinsi",
       x = NULL, y = NULL) +
  theme_minimal(base_size = 10) +
  theme(axis.text.x = element_text(angle = 60, hjust = 1, size = 7),
        plot.title = element_text(face = "bold", size = 11),
        plot.title.position = "plot")

1. Alasan perbaikan

  • Urutan provinsi acak terhadap nilainya. Provinsi disusun menurut letak geografis, sehingga pembaca tidak bisa langsung menemukan provinsi tertinggi, terendah, atau membuat peringkat.
  • 34 batang vertikal dengan label miring. Nama provinsi yang panjang harus diputar sehingga sulit dibaca
  • Tidak ada acuan pembanding. Pembaca tidak tahu provinsi mana yang tergolong tinggi atau rendah, karena tidak ada garis rata-rata.
  • Tidak ada label nilai, sehingga harus menebak nilai dari tinggi batang dan garis grid.

2. Perbaikan yang dilakukan

  • Mengubah menjadi diagram lollipop horizontal yang diurutkan dari nilai tertinggi ke terendah. Nama provinsi terbaca lurus, dan peringkat langsung terlihat.
  • Menambahkan garis putus-putus rata-rata antarprovinsi (14,7%) sebagai acuan.
  • Memakai dua warna bermakna: oranye untuk provinsi di atas rata-rata dan biru untuk yang di bawah rata-rata, sehingga kelompok tinggi dan rendah terpisah secara visual.
  • Menuliskan nilai pada setiap titik sehingga angka tepat bisa dibaca tanpa menebak.
  • Judul dibuat berupa kesimpulan (bukan sekadar deskripsi topik) agar pembaca tahu apa yang harus dilihat.
  • Garis grid dikurangi (hanya garis vertikal tipis) untuk mengurangi noise
komputer_baru <- komputer %>%
  mutate(
    status   = ifelse(persen >= rata2, "Di atas rata-rata", "Di bawah rata-rata"),
    provinsi = reorder(provinsi, persen)
  )

ggplot(komputer_baru, aes(x = persen, y = provinsi, color = status)) +
  geom_segment(aes(x = 0, xend = persen, yend = provinsi), linewidth = 0.7) +
  geom_vline(xintercept = rata2, linetype = "dashed", color = "grey30") +
  geom_point(size = 3) +
  geom_label(aes(label = fmt(persen, 2)), hjust = -0.25, size = 3.2,
             fill = "white", label.size = 0, label.padding = unit(0.1, "lines"),
             show.legend = FALSE) +
  annotate("text", x = rata2 + 0.3, y = 3.5, hjust = 0, size = 3.6,
           color = "grey20", lineheight = 1.0,
           label = paste0("Rata-rata antarprovinsi:\n", fmt(rata2), "%")) +
  scale_color_manual(values = c("Di atas rata-rata" = oranye,
                                "Di bawah rata-rata" = biru)) +
  scale_x_continuous(limits = c(0, 26), expand = c(0, 0),
                     breaks = seq(0, 25, 5),
                     labels = function(x) paste0(x, "%")) +
  labs(
    title = "Penggunaan komputer sangat timpang antarprovinsi",
    subtitle = paste0("Persentase penduduk pengguna komputer menurut provinsi, 2019.\n",
                      n_atas, " dari 34 provinsi berada di atas rata-rata."),
    x = NULL, y = NULL, color = NULL,
    caption = "Sumber: BPS (bps.go.id), situasi tahun 2019.\nRata-rata dihitung sederhana dari 34 provinsi (tidak dibobot jumlah penduduk)."
  ) +
  tema +
  theme(legend.position = "top",
        legend.justification = "left",
        panel.grid.major.y = element_blank(),
        axis.text.y = element_text(size = 9))

3. Interpretasi

Penggunaan komputer di Indonesia belum merata antarprovinsi. Persentase tertinggi dicapai DKI Jakarta (23,51%), disusul DI Yogyakarta (23,35%) dan Kep. Riau (20,72%), sedangkan yang terendah adalah Papua (8,20%), diikuti Lampung (9,94%) dan Kalimantan Barat (10,45%). Selisih tertinggi dan terendah mencapai sekitar 2,9 kali lipat. Rata-rata antarprovinsi sebesar 14,7%, dan hanya 13 dari 34 provinsi yang berada di atas rata-rata, artinya sebagian besar provinsi berada di bawah nilai tengah yang ditarik ke atas oleh segelintir provinsi bernilai tinggi. Secara umum, nilai yang tinggi cenderung ditemukan pada provinsi dengan kota besar atau pusat pendidikan (DKI Jakarta, DI Yogyakarta, Kep. Riau, Kalimantan Timur, Bali), sedangkan sejumlah provinsi di wilayah timur (Papua, Maluku, Maluku Utara, Nusa Tenggara) dan sebagian Sumatera (Lampung, Sumatera Selatan, Aceh) berada di kelompok bawah. Pola ini merupakan eksplorasi dari visualisasi data, dan perlu analisis lanjutan (misalnya akses listrik, internet, dan tingkat pendapatan) untuk memastikan penyebabnya.


Visualisasi 4: Kasus Harian Baru COVID-19 Dunia (Slide 10 - Noise vs Signal)

Sumber data: Worldometer, periode 22 Januari - 31 Agustus 2020.

Catatan mengenai data. Data mentah tidak tersedia, sehingga nilai kasus harian di bawah ini direkonstruksi dengan mengukur tinggi tiap batang pada gambar slide (223 hari). Sebagai validasi, rata-rata bergerak 7 hari yang saya hitung ulang dari nilai hasil rekonstruksi dibandingkan dengan garis biru pada gambar asli: korelasinya 0,9999 dan selisih rata-ratanya sekitar 1,7 ribu kasus (kurang dari 1% dari puncaknya). Jadi nilai berikut adalah pendekatan yang sangat dekat, bukan angka resmi harian. Jika Anda memiliki data asli (misalnya dari Worldometer atau Our World in Data), cukup ganti vektor kasus_ribu di bawah ini.

tanggal <- seq(as.Date("2020-01-22"), by = "day", length.out = 223)
# Kasus harian (dalam ribuan), hasil pembacaan tinggi batang pada slide 10
kasus_ribu <- c(
    0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 5, 5, 5, 2, 5, 5, 5,
    14, 6, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 3, 5, 5, 2, 6, 6, 8, 5, 6, 17, 17, 18, 20, 20, 26, 32, 36, 33, 35,
    42, 44, 48, 59, 62, 63, 56, 62, 71, 74, 77, 80, 78, 66, 71, 77, 81, 75, 89, 77,
    66, 69, 72, 78, 78, 81, 77, 71, 74, 72, 78, 78, 93, 86, 69, 66, 72, 77, 84, 92,
    80, 81, 78, 80, 92, 93, 93, 93, 77, 71, 87, 86, 95, 99, 93, 80, 92, 93, 102, 107,
    107, 99, 95, 89, 93, 107, 116, 125, 123, 123, 101, 116, 117, 131, 131, 129, 114, 108, 120, 137,
    138, 141, 134, 123, 125, 141, 146, 138, 182, 156, 131, 138, 162, 171, 179, 194, 176, 162, 161, 177,
    198, 207, 213, 194, 177, 170, 207, 213, 222, 236, 215, 198, 197, 218, 234, 246, 239, 225, 221, 204,
    239, 279, 275, 288, 260, 222, 219, 246, 288, 284, 290, 260, 222, 200, 252, 272, 282, 281, 269, 222,
    216, 266, 287, 287, 287, 260, 215, 200, 258, 273, 269, 260, 264, 207, 212, 246, 272, 272, 282, 258,
    221, 243, 260
)
stopifnot(length(kasus_ribu) == length(tanggal))

# Rata-rata bergerak "trailing" (hari ini dan k-1 hari sebelumnya), seperti pada Worldometer
rata_bergerak <- function(x, k) as.numeric(stats::filter(x, rep(1 / k, k), sides = 1))

covid <- data.frame(
  tanggal = tanggal,
  harian  = kasus_ribu * 1000,
  ma3     = rata_bergerak(kasus_ribu, 3) * 1000,
  ma7     = rata_bergerak(kasus_ribu, 7) * 1000
)

puncak7 <- covid[which.max(covid$ma7), ]
akhir   <- covid[nrow(covid), ]
bln_id  <- c("Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des")
tgl_id  <- function(d) paste(as.integer(format(d, "%d")), bln_id[as.integer(format(d, "%m"))])

Visualisasi Awal

Kasus harian sebagai batang abu-abu dan hanya satu garis rata-rata bergerak (7 hari) yang aktif. Garis rata-rata bergerak 3 hari tidak terlihat pada grafik.

# Meniru tampilan grafik asli Worldometer pada slide 10
tgl_en <- function(d) sprintf("%s %02d", month.abb[as.integer(format(d, "%m"))],
                              as.integer(format(d, "%d")))
legenda <- c("Daily Cases", "3-day moving average", "7-day moving average")

ggplot(covid, aes(x = tanggal)) +
  geom_col(aes(y = harian), fill = "#999999", width = 0.75) +
  # 3-day MA tidak digambar pada grafik asli (kotak pilihan tidak dicentang),
  # hanya muncul di legenda dengan warna abu pucat
  geom_line(aes(y = NA_real_, color = "3-day moving average"), na.rm = TRUE) +
  geom_point(aes(y = NA_real_, color = "3-day moving average"), na.rm = TRUE) +
  geom_point(aes(y = NA_real_, color = "Daily Cases"), na.rm = TRUE) +
  geom_line(aes(y = ma7, color = "7-day moving average"), linewidth = 0.9, na.rm = TRUE) +
  scale_color_manual(
    breaks = legenda,
    values = c("Daily Cases" = "#8C8C8C", "3-day moving average" = "#CFCFCF",
               "7-day moving average" = "#2CA3C6"),
    guide = guide_legend(override.aes = list(
      shape = c(16, 16, 18), linetype = c("blank", "solid", "solid"), size = c(5, 3, 3.5)))
  ) +
  scale_x_date(breaks = seq(as.Date("2020-01-22"), as.Date("2020-08-31"), by = "8 days"),
               labels = tgl_en, expand = expansion(mult = c(0.01, 0.005))) +
  scale_y_continuous(limits = c(0, 400000), expand = c(0, 0),
                     breaks = seq(0, 400000, 100000),
                     labels = function(x) ifelse(x == 0, "0", paste0(x / 1000, "k"))) +
  labs(title = "Daily New Cases", subtitle = "Cases per Day\nData as of 0:00 GMT+0",
       x = NULL, y = "Novel Coronavirus Daily Cases", color = NULL,
       caption = "Source: Worldometer - www.worldometers.info") +
  theme_minimal(base_size = 12) +
  theme(plot.title = element_text(hjust = 0.5, size = 18, margin = margin(b = 6)),
        plot.subtitle = element_text(hjust = 0.5, color = "grey25", size = 11),
        plot.caption = element_text(color = "grey45", size = 10),
        axis.text.x = element_text(angle = 45, hjust = 1, size = 9, color = "grey35"),
        axis.text.y = element_text(color = "grey35"),
        axis.title.y = element_text(color = "grey35", size = 11),
        panel.grid.minor = element_blank(), panel.grid.major.x = element_blank(),
        panel.grid.major.y = element_line(color = "grey90"),
        legend.position = "bottom", legend.text = element_text(size = 11))

1. Alasan perbaikan

  • Garis rata-rata bergerak 3 hari tidak terlihat.
  • Hierarki visual tidak jelas. Batang abu-abu (data mentah dengan banyak noise) dan garis tipis berwarna biru muda berebut perhatian, sehingga garis rata-rata kurang menonjol.
  • Legenda terpisah dari data, sehingga pembaca harus mencocokkan warna di bawah grafik dengan elemen di atas.
  • Sumbu horizontal sulit dibaca. Label tanggal miring setiap 8 hari dan tidak selaras dengan awal bulan.
  • Tidak ada pesan utama: judul hanya “Daily New Cases”, tanpa sorotan pada tren atau puncak.

2. Perbaikan yang dilakukan

  • Menampilkan ketiga lapisan secara eksplisit dengan perbedaan yang tegas: data harian sebagai batang abu-abu sangat muda (sebagai noise latar), rata-rata 3 hari sebagai garis hijau tosca, dan rata-rata 7 hari sebagai garis biru tua tebal (sebagai signal). Warna dan ketebalan berbeda sehingga ketiganya terpisah jelas, dan urutan “makin tebal = makin halus” membantu pembaca.
  • Label langsung di ujung garis menggantikan legenda sehingga tidak perlu mencocokkan warna.
  • Sumbu x per bulan dengan label horizontal berbahasa Indonesia, dan sumbu y memakai satuan “rb” (ribu) sehingga angkanya ringkas.
  • Sorotan titik tertinggi rata-rata 7 hari sebagai penanda pesan utama, dan judul berupa kesimpulan.
  • Batang harian diberi garis tepi abu-abu tipis dan sedikit celah antarbatang, sehingga setiap hari tetap terbaca sebagai batang tersendiri (tidak melebur menjadi satu area abu-abu), namun warna isinya tetap muda agar tidak mengalahkan garis rata-rata.
  • Menghapus garis grid vertikal dan elemen yang tidak perlu agar fokus pada tren.
n <- nrow(covid)
x_akhir <- covid$tanggal[n]

ggplot(covid, aes(x = tanggal)) +
  geom_col(aes(y = harian), fill = "grey90", color = "grey50",
           linewidth = 0.25, width = 0.85) +
  geom_line(aes(y = ma3), color = "#1cebc4", linewidth = 0.6, na.rm = TRUE) +
  geom_line(aes(y = ma7), color = "#0B3C6F", linewidth = 1.6, na.rm = TRUE) +
  geom_point(data = puncak7, aes(y = ma7), color = "#0B3C6F", size = 3) +
  annotate("text", x = puncak7$tanggal, y = 322000, color = "#0B3C6F",
           fontface = "bold", size = 3.8, lineheight = 1.0,
           label = paste0("Titik tertinggi rata-rata 7 hari:\n~", round(puncak7$ma7 / 1000),
                          " ribu kasus/hari (", tgl_id(puncak7$tanggal), ")")) +
  annotate("text", x = x_akhir + 3, y = akhir$ma7 + 22000, hjust = 0, size = 3.6,
           color = "#0B3C6F", fontface = "bold", lineheight = 0.95,
           label = "Rata-rata\nbergerak 7 hari") +
  annotate("text", x = x_akhir + 3, y = akhir$ma3 - 20000, hjust = 0, size = 3.6,
           color = "#1cebc4", fontface = "bold", lineheight = 0.5,
           label = "Rata-rata\nbergerak 3 hari") +
  annotate("text", x = x_akhir + 3, y = 120000, hjust = 0, size = 3.6,
           color = "grey45", lineheight = 0.95,
           label = "Kasus harian\n(batang)") +
  scale_x_date(breaks = c(as.Date("2020-01-22"),
                          seq(as.Date("2020-02-01"), as.Date("2020-09-01"), by = "month")),
               labels = function(d) bln_id[as.integer(format(d, "%m"))],
               expand = expansion(mult = c(0.01, 0.15))) +
  scale_y_continuous(labels = function(x) paste0(x / 1000, " rb"),
                     limits = c(0, 350000), breaks = seq(0, 300000, 100000),
                     expand = c(0, 0)) +
  labs(
    title = "Rata-rata bergerak meredam noise dan menyingkap tren kasus harian dunia",
    subtitle = "Kasus baru COVID-19 per hari di seluruh dunia, 22 Januari - 31 Agustus 2020",
    x = NULL, y = "Kasus baru per hari (ribu)",
    caption = "Sumber: Worldometer - www.worldometers.info"
  ) +
  tema +
  theme(
    panel.grid.major.x = element_blank(),
    axis.title.y = element_text(size = 11),
    plot.caption = element_text(hjust = 1) # Rata kanan (kanan bawah)
  )

3. Interpretasi

Grafik menampilkan jumlah kasus baru COVID-19 per hari di seluruh dunia pada periode 22 Januari - 31 Agustus 2020. Batang abu-abu menunjukkan data harian yang berfluktuasi tajam dari hari ke hari (noise), terlihat dari pola naik-turun yang berulang. Garis oranye (rata-rata 3 hari) meredam sebagian fluktuasi itu, dan garis biru tua (rata-rata 7 hari) dengan pola garis lebih halus sehingga arah tren (signal) terlihat jelas.

Dari garis 7 hari terbaca tiga fase. Pertama, kasus harian dunia masih sangat rendah pada Januari-Februari. Kedua, kasus naik pesat sepanjang Maret hingga mencapai sekitar 75-80 ribu per hari pada awal April, lalu relatif mendatar di kisaran 75-90 ribu hingga akhir Mei. Ketiga, kasus naik lagi dengan cepat sejak awal Juni hingga sekitar 260 ribu per hari pada akhir Juli, kemudian mendatar di kisaran 250-260 ribu hingga akhir Agustus. Titik tertinggi rata-rata 7 hari berada di sekitar 262 ribu kasus per hari pada 13 Agu, hanya sedikit di atas level mendatar tersebut. Pada akhir Agustus, rata-ratanya 258 ribu per hari, sehingga belum terlihat penurunan yang jelas.

Visualisasi 5: Peta Sebaran Presentase Kemiskinan

1. Alasan perbaikan

  • Kontras Warna Rendah: Peta awal menggunakan gradasi warna biru kontinu dengan rentang yang sangat halus, sehingga perbedaan tingkat kemiskinan antarprovinsi sulit dibedakan secara cepat.

  • Klasifikasi Data Kurang Jelas: Penggunaan skala kontinu tanpa pembagian rentang (class breaks) menyulitkan pembaca untuk menentukan interval persentase pasti suatu wilayah.

  • Elemen Tidak Lengkap: Peta awal belum dilengkapi dengan penunjuk arah mata angin (north arrow) dan skala peta (scale bar) sebagai standar visualisasi geografis.

2. Perbaikan yang dilakukan

  • Penggunaan Palet Warna Kontras (YlOrRd): Mengubah skala kontinu menjadi skema warna berurutan (kuning ke merah tua) yang intuitif, di mana warna kuning menandakan tingkat rendah dan merah tua menandakan tingkat tinggi.

  • Diskretisasi 6 Rentang Kategori: Membagi data ke dalam 6 kelas interval yang terukur (0%-5%, >5%-10%, >10%-15%, >15%-20%, >20%-25%, >25%-30%) beserta legenda terstruktur di bawah peta.

  • Penambahan Kelengkapan Peta: Menambahkan arah mata angin di kanan atas, batang skala (1000 km) di kiri bawah, serta tata letak judul, subjudul, dan caption sumber data yang informatif.

library(sf)
library(geodata)
dir.create("cache_peta", showWarnings = FALSE)
library(ggplot2)
library(ggspatial) # Package tambahan untuk arah mata angin dan skala peta

# 1. Mengunduh batas provinsi
provinsi <- geodata::gadm(
  country = "IDN",
  level = 1,
  version = "3.6",
  path = "cache_peta"
)

peta_prov <- st_as_sf(provinsi)

# 2. Simulasi persentase kemiskinan
set.seed(123)

peta_prov$kemiskinan <- round(
  runif(nrow(peta_prov), min = 4, max = 28),
  digits = 1
)

# Membagi data kontinu menjadi 6 rentang kategori
peta_prov$kemiskinan_kat <- cut(
  peta_prov$kemiskinan,
  breaks = c(0, 5, 10, 15, 20, 25, 30),
  labels = c("0% - 5%", ">5% - 10%", ">10% - 15%", ">15% - 20%", ">20% - 25%", ">25% - 30%"),
  include.lowest = TRUE
)

# 3. Membuat peta dengan 6 rentang warna, arah mata angin, dan skala
ggplot(peta_prov) +
  geom_sf(
    aes(fill = kemiskinan_kat),
    color = "white",
    linewidth = 0.25
  ) +
  
  # Palet 6 warna berurutan yang kontras dan menarik (YlOrRd - Yellow Orange Red)
  scale_fill_brewer(
    palette = "YlOrRd",
    name = "Persentase Kemiskinan",
    na.value = "#D9D9D9",
    guide = guide_legend(
      direction = "horizontal",
      title.position = "top",
      title.hjust = 0.5,
      nrow = 1
    )
  ) +
  
  # Komponen 1: Skala Batang Peta (Scale Bar)
  annotation_scale(
    location = "bl", # Posisi kiri bawah (bottom-left)
    width_hint = 0.2,
    style = "ticks"
  ) +
  
  # Komponen 2: Arah Mata Angin (North Arrow)
  annotation_north_arrow(
    location = "tr", # Posisi kanan atas (top-right)
    which_north = "true",
    pad_x = unit(0.5, "cm"),
    pad_y = unit(0.5, "cm"),
    style = north_arrow_fancy_orienteering(
      fill = c("grey40", "white"),
      line_col = "black"
    )
  ) +
  
  coord_sf(
    datum = NA,
    expand = FALSE
  ) +
  labs(
    title = "Persentase Kemiskinan Menurut Provinsi",
    subtitle = "Klasifikasi 6 rentang tingkat kemiskinan provinsi di Indonesia",
    caption = paste(
      "Data kemiskinan: simulasi untuk latihan",
      "Batas wilayah: GADM",
      sep = " | "
    )
  ) +
  theme_void(base_size = 13) +
  theme(
    plot.title = element_text(
      face = "bold",
      size = 18,
      hjust = 0.5
    ),
    plot.subtitle = element_text(
      size = 11,
      color = "#555555",
      hjust = 0.5,
      margin = margin(t = 6, b = 15)
    ),
    legend.position = "bottom",
    legend.title = element_text(size = 11, face = "bold"),
    legend.text = element_text(size = 9),
    plot.caption = element_text(
      size = 9,
      color = "#666666",
      hjust = 0
    ),
    plot.background = element_rect(
      fill = "white",
      color = NA
    ),
    plot.margin = margin(15, 20, 15, 20)
  )

3. Interpretasi

  • Tingkat Kemiskinan Tinggi (>20% – 30%): Ditunjukkan oleh wilayah berwarna merah tua hingga merah gelap (seperti beberapa provinsi di Sumatra, Nusa Tenggara, dan Papua), mengindikasikan area dengan persentase kemiskinan tertinggi.

  • Tingkat Kemiskinan Sedang (>10% – 20%): Ditunjukkan oleh wilayah berwarna oranye hingga oranye tua (sebagian besar Kalimantan, Sulawesi, dan Jawa).

  • Tingkat Kemiskinan Rendah (0% – 10%): Ditunjukkan oleh wilayah berwarna kuning terang hingga kuning muda, mencerminkan daerah dengan tingkat kemiskinan yang relatif paling kecil.


Ringkasan Perbaikan

Visualisasi Jenis awal Jenis baru Prinsip utama yang diterapkan
Keterisian tempat tidur RS DKI Diagram lingkaran 3D Diagram garis Jenis grafik sesuai tipe data (deret waktu); hilangkan efek 3D
Sistem pembayaran Diagram lingkaran Diagram lingkaran Perbaikan warna dan posisi legend
Pengguna komputer per provinsi Batang vertikal (urutan geografis) Lollipop horizontal terurut Urutan bermakna, acuan rata-rata, label langsung
Kasus harian COVID-19 dunia Batang + 1 garis (7 hari), 3 hari tak tampil Penambahan garis 3 day moving average Hierarki visual (noise vs signal), label langsung, highlight puncak
Peta Sebaran Presentase Kemiskinan Peta Choropleth

Peta Choropleth

(dengan perbaikan)

  1. Penambahan arah kompas dan skala
  2. Penyesuaian warna agar mudah diinterpretasikan
## R version: R version 4.5.2 (2025-10-31)