Basic Data Visualization

Practicum ~ Week 4

Logo


1. Pendahuluan

1.1 Tujuan

Dataset ini digunakan untuk menganalisis kinerja pembelajaran siswa berdasarkan beberapa faktor seperti jenis kelamin, jumlah ketidakhadiran, dan waktu belajar mandiri per minggu. Tujuannya adalah untuk:

  • Melihat hubungan antara kebiasaan belajar dengan hasil akademik di berbagai mata pelajaran,
  • Mengidentifikasi pola yang memengaruhi prestasi siswa, dan
  • Membantu guru atau peneliti memahami faktor-faktor yang paling berpengaruh terhadap nilai siswa.

1.2 Deskripsi Dataset

# VARIABLE CLASSIFICATION TABLE – Learning Performance Dataset

# 1. Load Required Libraries 
library(knitr)
library(kableExtra)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:kableExtra':
## 
##     group_rows
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
# 2. Create Variable Classification Table 
variable_classification <- data.frame(
  Column = c(
    "first_name", 
    "gender", 
    "absence_days", 
    "weekly_self_study_hours", 
    "math_score", 
    "history_score", 
    "physics_score", 
    "chemistry_score", 
    "biology_score", 
    "english_score", 
    "geography_score"
  ),
  
  Data_Type = c(
    "Categorical", 
    "Categorical", 
    "Numerical", 
    "Numerical", 
    "Numerical", 
    "Numerical", 
    "Numerical", 
    "Numerical", 
    "Numerical", 
    "Numerical", 
    "Numerical"
  ),
  
  Subtype = c(
    "Nominal", 
    "Nominal", 
    "Discrete", 
    "Continuous", 
    "Continuous", 
    "Continuous", 
    "Continuous", 
    "Continuous", 
    "Continuous", 
    "Continuous", 
    "Continuous"
  ),
  
  Description = c(
    "Student's first name", 
    "Student's gender (male/female)", 
    "Number of days the student was absent", 
    "Average number of self-study hours per week", 
    "Score obtained in Mathematics", 
    "Score obtained in History", 
    "Score obtained in Physics", 
    "Score obtained in Chemistry", 
    "Score obtained in Biology", 
    "Score obtained in English", 
    "Score obtained in Geography"
  )
)

# 3. Generate Styled Table 
variable_classification %>%
  kbl(
    caption = "Table 1. Variable Classification for the Learning Performance Dataset",
    align = c("l", "c", "c", "l"),  # align columns (left for 1 & 4)
    col.names = c("Column", "Data Type", "Subtype", "Description"),
    escape = FALSE
  ) %>%
  kable_classic(full_width = FALSE, html_font = "Poppins") %>%
  
  # Apply pastel background per column + alignment fix
  column_spec(1, bold = TRUE, color = "#3A3A3A", background = "#FFE6E6", width = "4cm", extra_css = "text-align: left;") %>%  
  column_spec(2, color = "#3A3A3A", background = "#E6E6FA", width = "3cm") %>%               
  column_spec(3, color = "#3A3A3A", background = "#E0F7FA", width = "3cm") %>%               
  column_spec(4, color = "#3A3A3A", background = "#E8F5E9", width = "8cm", extra_css = "text-align: left;") %>%               
  
  # Add top header (pastel title bar)
  add_header_above(
    c("Data Description Table" = 4), 
    bold = TRUE, 
    color = "white", 
    background = "#B4C7E7",  
    line = TRUE
  ) %>%
  
  # Apply global styling
  kable_styling(
    bootstrap_options = c("hover", "condensed", "responsive"),
    position = "center",
    font_size = 14,
    fixed_thead = TRUE
  )
Table 1. Variable Classification for the Learning Performance Dataset
Data Description Table
Column Data Type Subtype Description
first_name Categorical Nominal Student’s first name
gender Categorical Nominal Student’s gender (male/female)
absence_days Numerical Discrete Number of days the student was absent
weekly_self_study_hours Numerical Continuous Average number of self-study hours per week
math_score Numerical Continuous Score obtained in Mathematics
history_score Numerical Continuous Score obtained in History
physics_score Numerical Continuous Score obtained in Physics
chemistry_score Numerical Continuous Score obtained in Chemistry
biology_score Numerical Continuous Score obtained in Biology
english_score Numerical Continuous Score obtained in English
geography_score Numerical Continuous Score obtained in Geography

Totalnya dataset ini mencakup data performa siswa di tujuh mata pelajaran utama, serta kebiasaan dan faktor personal yang bisa memengaruhi nilai mereka.

1.3 Konteks Kasus

Dataset ini bisa dianggap sebagai data hasil survei atau observasi di sebuah sekolah menengah atau universitas. Fokusnya adalah untuk:

  • Mengetahui apakah siswa yang belajar lebih banyak jamnya per minggu mendapatkan nilai lebih
    tinggi,
  • Melihat pengaruh absensi terhadap prestasi belajar, dan
  • Membandingkan performa akademik antara siswa laki-laki dan perempuan.

Dengan analisis ini, bisa dibuat kesimpulan seperti: “Siswa dengan tingkat kehadiran tinggi dan jam belajar mandiri lebih banyak cenderung memiliki nilai yang lebih baik di sebagian besar mata pelajaran.”

2. Persiapan Data

# DATA PREPARATION: Clean, Process, and Display Interactive Table
library(readxl)
library(dplyr)
library(reactable)
library(htmltools)

# 1. Import dataset
data_raw <- read_excel("kinerja pembelajaran (statistik).xlsx")

# 2. Clean and prepare data
data_clean <- data_raw %>%
  rename_with(~ gsub("\\s+", "_", .x)) %>%
  mutate(across(where(is.character), trimws)) %>%
  mutate(
    RecordID = sprintf("R%04d", 1:n()),
    EntryDate = Sys.Date(),
    RandomScore = round(runif(n(), 60, 100), 1)
  )

# 3. Create interactive table with dropdown + animated pagination
htmltools::browsable(
  htmltools::tagList(
    
    # Dropdown control for entries per page
    tags$div(
      style = "display:flex; align-items:center; gap:6px; margin-bottom:10px; font-size:14px;",
      tags$span("Showing"),
      tags$select(
        id = "pageSizeSelect",
        style = "padding:3px 6px; border-radius:4px; border:1px solid #ccc; font-size:14px;",
        tags$option(value = 10, "10"),
        tags$option(value = 25, "25"),
        tags$option(value = 50, "50"),
        tags$option(value = 100, "100")
      ),
      tags$span("entries")
    ),
    
    # Reactable table
    reactable(
      data_clean,
      elementId = "myTable",
      searchable = TRUE,
      bordered = TRUE,
      striped = TRUE,
      highlight = TRUE,
      resizable = TRUE,
      defaultPageSize = 10,
      wrap = FALSE,
      fullWidth = TRUE,
      defaultColDef = colDef(align = "center"),
      
      theme = reactableTheme(
        headerStyle = list(
          background = "#f7f7f7",
          fontWeight = "bold",
          borderBottom = "2px solid #ddd"
        ),
        
        # Pagination area (clear background)
        paginationStyle = list(
          background = "transparent",
          borderTop = "1px solid #ddd",
          padding = "8px 0"
        ),
        
        # Pagination buttons with animation
        pageButtonStyle = list(
          background = "#ffffff",
          border = "1px solid #90CAF9",
          color = "#0D47A1",
          borderRadius = "6px",
          padding = "4px 10px",
          margin = "0 3px",
          transition = "all 0.2s ease-in-out",
          boxShadow = "0 1px 3px rgba(0,0,0,0.1)",
          fontWeight = "500"
        ),
        pageButtonHoverStyle = list(
          background = "#E3F2FD",
          border = "1px solid #42A5F5",
          transform = "scale(1.05)"
        ),
        pageButtonActiveStyle = list(
          background = "#1E88E5",
          color = "white",
          transform = "scale(1.05)"
        )
      )
    ),
    
    # JavaScript to change number of entries dynamically
    tags$script(HTML("
      document.getElementById('pageSizeSelect').addEventListener('change', function() {
        const newSize = parseInt(this.value);
        const tbl = window.reactable.getInstance('myTable');
        if (tbl) tbl.setPageSize(newSize);
      });
    "))
  )
)
Showing entries

3. Visualisasi

3.1 Bar Chart

  • Definisi

    Bar Chart adalah jenis visualisasi data yang digunakan untuk mewakili Data kategoris dengan bar persegi panjang. Setiap tinggi (atau panjang) bar sesuai dengan nilai atau frekuensi suatu kategori, sehingga mudah untuk membandingkan jumlah di berbagai kelompok.

  • Aturan Penggunaan

    1. Gunakan untuk data kategorikal seperti kota, jenis barang, jurusan, atau tingkat kepuasan.

    2. Batang mewakili nilai atau frekuensi dari tiap kategori.

    3. Tinggi atau panjang batang harus proporsional terhadap nilai datanya.

    4. Sumbu X atau Y harus diberi label dengan jelas (kategori dan nilai).

    5. Gunakan jarak antar batang yang sama, agar perbandingan mudah dibaca.

    6. Warna dan ukuran batang konsisten, jangan terlalu ramai agar tidak membingungkan.

    7. Cocok dipakai untuk:

      • Data numerik diskrit, seperti jumlah barang atau frekuensi.
      • Data kategoris ordinal, seperti tingkat kepuasan (rendah, sedang, tinggi).
  • Kelebihan

    1. Mudah dipahami secara visual, bahkan oleh orang awam.
    2. Memudahkan perbandingan antar kategori (mana yang lebih tinggi/rendah).
    3. Dapat menunjukkan pola atau tren sederhana secara cepat.
    4. Fleksibel: bisa vertikal, horizontal, atau bertumpuk (stacked).
    5. Cocok digunakan untuk menunjukkan kontribusi tiap kategori (misalnya total penjualan per kota).
  • Kekurangan

    1. Tidak cocok untuk data waktu berkelanjutan (time series) lebih baik pakai line chart.
    2. Jika kategorinya terlalu banyak, grafik jadi sulit dibaca dan padat.
    3. Perbedaan kecil antar batang kadang sulit dibedakan secara visual.
    4. Tidak bisa menunjukkan hubungan antar variabel, hanya membandingkan satu variabel terhadap kategori.
library(ggplot2)
library(dplyr)
library(readxl)

data <- read_excel("kinerja pembelajaran (statistik).xlsx", sheet = "Lembar1")

# Hitung jumlah siswa per kategori gender
gender_count <- data %>%
  group_by(gender) %>%
  summarise(Jumlah_Siswa = n())

# Bar chart
ggplot(gender_count, aes(x = gender, y = Jumlah_Siswa, fill = gender)) +
  geom_bar(stat = "identity", width = 0.6) +
  geom_text(aes(label = Jumlah_Siswa), vjust = -0.5, size = 4, color = "black") +
  scale_fill_manual(values = c("#FFB6B9", "#BBDED6")) + 
  labs(
    title = "Jumlah Siswa Berdasarkan Gender",
    x = "Gender",
    y = "Jumlah Siswa"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 14, face = "bold"),
    axis.text = element_text(size = 10),
    legend.position = "none"
    )

3.2 Histogram

  • Definisi

    Histogram adalah representasi grafis dari distribusi data numerik. Histogram membagi data ke dalam interval, yang dikenal sebagai bin, dan menampilkan frekuensi titik data dalam setiap bin. Visualisasi ini membantu mengidentifikasi pola-pola seperti
    tendensi sentral, sebaran, kemiringan, dan keberadaan beberapa modus dalam data
    (Wickham2016).

  • Aturan Penggunaan

    1. Gunakan untuk data numerik (berupa angka) bukan data kategori.
    2. Data dibagi menjadi beberapa interval atau “bin”, misalnya 0–10, 10–20, dst.
    3. Tinggi batang menunjukkan frekuensi (berapa banyak data) dalam setiap bin.
    4. Tidak boleh ada jarak antar batang, karena histogram menunjukkan rentang nilai yang berurutan (kontinu).
    5. Sumbu X = interval data, sumbu Y = frekuensi kemunculan data.
    6. Cocok digunakan untuk:
      • Mengetahui bentuk distribusi data (normal, miring, atau bimodal).
      • Melihat sebaran dan kecenderungan nilai dalam dataset.
  • Kelebihan

    1. Bisa menunjukkan pola sebaran data angka dengan jelas (misalnya data miring ke
      kanan, normal, atau punya dua puncak).
    2. Membantu kita melihat di rentang mana data paling banyak muncul — jadi tahu nilai yang sering keluar.
    3. Mudah dibaca dan dipahami secara visual, jadi cocok buat menjelaskan data ke orang
      awam.
    4. Bisa membantu mendeteksi penyimpangan atau data yang aneh (outlier).
    5. Berguna untuk menilai rata-rata, persebaran, dan kecenderungan data secara umum.
  • Kekurangan

    1. Hanya cocok untuk data numerik kontinu, tidak bisa untuk kategori seperti nama
      kota atau jenis barang.
    2. Pemilihan jumlah bin (interval) sangat memengaruhi tampilan — terlalu sedikit bin
      membuat data tampak kasar, terlalu banyak bin membuat data tampak acak.
    3. Sulit dibandingkan antar kelompok jika lebih dari satu dataset.
    4. Tidak menunjukkan nilai individu, hanya kelompok intervalnya.
    5. Jika datanya sedikit, hasil histogram bisa menyesatkan atau tidak representatif.
# Set CRAN mirror (biar bisa install package tanpa error)
options(repos = c(CRAN = "https://cloud.r-project.org"))

library(readxl)
library(ggplot2)
library(tidyr)
library(dplyr)

data <- read_excel("kinerja pembelajaran (statistik).xlsx")

# Ubah jadi long format 
data_long <- data %>%
  pivot_longer(
    cols = c(math_score, history_score, physics_score, chemistry_score, biology_score, english_score, geography_score),
    names_to = "subject",
    values_to = "score"
  )

# histogram
ggplot(data_long, aes(x = score, fill = subject)) +
  geom_histogram(bins = 8, color = "white", alpha = 0.9) +
  scale_fill_manual(values = c("#FFB7B2", "#FFD1DC", "#B5EAD7", "#C7CEEA", "#FDFD96", "#E2F0CB", 
                               "#E0BBE4")) +
  facet_wrap(~subject, scales = "free_y") +
  labs(
    title = "Distribution of Student Scores per Subject",
    x = "Score",
    y = "Frequency"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    legend.position = "none",
    strip.text = element_text(face = "bold", color = "#E75480"),
    plot.title = element_text(face = "bold", color = "#E75480", hjust = 0.5)
  )

3.3 Boxplot

  • Definisi Boxplot adalah representasi visual dari distribusi data yang meringkas ringkasan lima angka utama: minimum, kuartil pertama (Q1), median (Q2), kuartil ketiga (Q3), dan maksimum.

  • Aturan Penggunaan

    1. Digunakan untuk menunjukkan penyebaran dan sebaran data angka (data numerik).
    2. Menampilkan nilai minimum, maksimum, median (nilai tengah), kuartil bawah, dan
      kuartil atas dalam satu gambar.
    3. Cocok dipakai untuk membandingkan sebaran data dari beberapa kelompok (misalnya
      nilai siswa per kelas, atau penghasilan antar daerah).
    4. Outlier (data yang jauh berbeda) bisa terlihat jelas lewat titik di luar “kotak”.
    5. Pastikan datanya berupa data kontinu atau numerik, bukan data kategori.
  • Kelebihan

    1. Mudah melihat sebaran dan persebaran data secara keseluruhan.
    2. Bisa menunjukkan median, variasi, dan outlier dalam satu tampilan.
    3. Cocok untuk membandingkan beberapa kelompok data sekaligus.
    4. Efisien, karena meringkas banyak data hanya dengan satu diagram.
    5. Membantu mendeteksi data yang tidak normal atau menyimpang.
  • Kekurangan

    1. Tidak menunjukkan detail tiap data, hanya ringkasan (seperti median dan kuartil).
    2. Sulit dipahami oleh orang awam yang belum terbiasa dengan konsep median atau
      kuartil.
    3. Tidak cocok untuk data kategori atau nominal.
    4. Tidak menunjukkan pola distribusi secara lengkap, hanya bentuk umum dan jangkauannya
      saja.
library(readxl)
library(tidyr)
library(ggplot2)
library(dplyr)

data <- read_excel("kinerja pembelajaran (statistik).xlsx")

data_long <- data %>%
  pivot_longer(
    cols = c(biology_score, chemistry_score, english_score,
             geography_score, history_score, math_score, physics_score),
    names_to = "Subject",
    values_to = "Score"
    )

ggplot(data_long, aes(x = gender, y = Score, fill = gender)) +
  geom_boxplot(alpha = 0.85, color = "white", outlier.shape = 21, outlier.fill = "#FFB6C1") +
  facet_wrap(~ Subject, ncol = 3) +
  scale_fill_manual(
    values = c(
      "female" = "#FFB6C1",  
      "male"   = "#A7C7E7"
    )
  ) +
  labs(
    title = "Boxplot of All Subject Scores by Gender",
    x = "Gender",
    y = "Score"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", color = "#E75480"),
    strip.text = element_text(face = "bold", color = "#444444"),
    axis.title.x = element_text(face = "bold"),
    axis.title.y = element_text(face = "bold"),
    legend.position = "none",
    panel.grid.major.x = element_blank()
  )

3.4 Pie chart

  • Definisi

    Pie chart adalah jenis grafik lingkaran yang digunakan untuk menampilkan data dalam bentuk proporsi berdasarkan bagian-bagian lingkaran, dengan masing-masing bagian mencerminkan
    persentase dari keseluruhan.

  • Aturan Penggunaan

    1. Dipakai untuk menunjukkan perbandingan bagian terhadap keseluruhan (misalnya persentase penjualan tiap produk atau proporsi jenis kelamin).
    2. Total seluruh bagian harus 100% atau satu kesatuan penuh (1 lingkaran = 100%).
    3. Cocok digunakan untuk data kategori yang jumlahnya tidak terlalu banyak (idealnya 3–6
      kategori).
    4. Setiap potongan (slice) mewakili persentase atau jumlah dari tiap kategori.
    5. Gunakan warna yang berbeda dan kontras agar tiap bagian mudah dibedakan.
    6. Jangan gunakan jika kategori terlalu banyak atau nilainya mirip — nanti hasilnya susah
      dibaca.
  • Kelebihan

    1. Mudah dipahami secara visual, terutama untuk melihat proporsi bagian terhadap keseluruhan.
    2. Menarik secara tampilan dan sering dipakai dalam presentasi atau laporan umum.
    3. Memudahkan kita melihat bagian mana yang paling besar dan paling kecil.
    4. Cocok untuk menampilkan data sederhana dengan sedikit kategori.
  • Kekurangan

    1. Sulit dibandingkan antar kategori kalau ukuran potongannya mirip.
    2. Tidak cocok kalau terlalu banyak kategori, karena potongannya jadi kecil dan membingungkan.
    3. Tidak bisa menunjukkan perubahan dari waktu ke waktu (lebih baik pakai line chart untuk itu).
    4. Tidak akurat untuk analisis mendetail, karena ukuran visual potongan kadang menipu.
    5. Sulit dibaca jika tanpa label atau persentase yang jelas.
library(readxl)
library(ggplot2)
library(dplyr)
library(tidyr)
library(scales)

data <- read_excel("kinerja pembelajaran (statistik).xlsx")

names(data) <- tolower(names(data))

# Ubah ke format long (gabungkan semua nilai pelajaran)
data_long <- data %>%
  pivot_longer(
    cols = c(biology_score, chemistry_score, english_score,
             geography_score, history_score, math_score, physics_score),
    names_to = "Mata_Pelajaran",
    values_to = "Nilai"
  )

# Hitung proporsi gender per mata pelajaran 
proporsi_data <- data_long %>%
  group_by(Mata_Pelajaran, gender) %>%
  summarise(Jumlah = n(), .groups = "drop_last") %>%
  mutate(Proporsi = Jumlah / sum(Jumlah)) %>%
  ungroup()

# Warna pastel 
  warna_pastel <- c("#FFB6C1", "#A7C7E7")

    proporsi_data$Mata_Pelajaran <- gsub("_", " ", proporsi_data$Mata_Pelajaran)
    proporsi_data$Mata_Pelajaran <- tools::toTitleCase(proporsi_data$Mata_Pelajaran)

# Plot Pie Chart per Mata Pelajaran
ggplot(proporsi_data, aes(x = "", y = Proporsi, fill = gender)) +
  geom_col(width = 1, color = "white", alpha = 0.95) +
  coord_polar(theta = "y") +
  facet_wrap(~ Mata_Pelajaran, ncol = 3) +
  geom_text(aes(label = paste0(round(Proporsi * 100), "%")),
            position = position_stack(vjust = 0.5),
            color = "white", size = 4, fontface = "bold") +
  
  scale_fill_manual(values = warna_pastel, name = "Gender") +
  labs(
    title = "Hubungan Antara Gender dan Nilai Tiap Mata Pelajaran",
    subtitle = "Setiap diagram menunjukkan proporsi gender dalam tiap pelajaran",
    fill = "Gender"
  ) +
  theme_void(base_size = 13) +
  theme(
    plot.background = element_rect(fill = "#FFF8FB", color = NA),
    legend.background = element_rect(fill = "#FFF8FB", color = NA),
    legend.position = "bottom",
    panel.spacing = unit(1.3, "lines"),
    plot.title = element_text(
      size = 18, face = "bold", hjust = 0.5, color = "#C71585",
      margin = margin(b = 5)
    ),
    plot.subtitle = element_text(
      size = 12, hjust = 0.5, color = "#8B008B",
      margin = margin(b = 10)
    ),
    # Label tiap mata pelajaran (facet title)
    strip.background = element_rect(fill = "#FADADD", color = NA),
    strip.text = element_text(size = 9.5, face = "bold", color = "#4B2E83"),
    # Legend
    legend.title = element_text(size = 11, face = "bold"),
    legend.text = element_text(size = 10)
    )

3.5 Scatter Plot

  • Definisi

    Scatter plot atau diagram sebar adalah grafik yang menampilkan titik-titik data di bidang koordinat (X dan Y). Setiap titik menunjukkan dua nilai — satu untuk sumbu X dan satu untuk sumbu Y. Diagram ini dipakai untuk melihat hubungan atau pola antara dua variable

  • Aturan Penggunaan

  1. Gunakan saat kamu ingin melihat hubungan (korelasi) antara dua data angka.
  2. Sumbu X dan Y harus berisi variabel numerik.
  3. Setiap titik mewakili satu pasangan data (X, Y).
  4. Cocok untuk data yang banyak, supaya pola hubungan terlihat jelas.
  5. Kalau perlu, tambahkan garis tren (trend line) agar arah hubungan (positif, negatif, atau tidak ada hubungan) lebih mudah dilihat.
  • Kelebihan
  1. Bisa menunjukkan hubungan atau korelasi antara dua variabel dengan jelas.
  2. Mudah melihat pola — apakah data naik bersama, turun bersama, atau tidak berhubungan sama sekali.
  3. Dapat membantu mendeteksi outlier (data yang jauh dari pola umum).
  4. Cocok untuk analisis awal (eksplorasi data) sebelum melakukan perhitungan statistik.
  5. Bisa memperlihatkan kekuatan dan arah hubungan antara dua variabel.
  • Kekurangan
  1. Tidak cocok untuk data kategori, hanya bisa untuk data angka.
  2. Sulit dibaca jika data terlalu banyak dan titik-titiknya saling menumpuk.
  3. Tidak bisa menunjukkan hubungan sebab-akibat, hanya hubungan atau pola.
  4. Kalau tidak diberi penjelasan tambahan, orang awam bisa salah tafsir tentang
    maknanya.
  5. Tidak menunjukkan rata-rata atau sebaran seperti box plot atau histogram.
library(readxl)
library(ggplot2)
library(dplyr)
library(tidyr)

data <- read_excel("kinerja pembelajaran (statistik).xlsx")

names(data) <- make.names(names(data))

# Pilih hanya kolom numerik
numeric_data <- data %>% select(where(is.numeric))

# Variabel acuan
y_var <- "absence.days"

# Ubah data ke format panjang
plot_data <- numeric_data %>%
  pivot_longer(cols = -all_of(y_var), names_to = "Mata_Pelajaran", values_to = "Nilai")

ggplot(plot_data, aes(x = Nilai, y = !!sym(y_var))) +
  geom_point(
    color = "#90CAF9",  
    fill = "#BBDEFB",
    shape = 21,
    alpha = 0.8,
    size = 3.5
  ) +
  geom_smooth(
    method = "lm",
    se = FALSE,
    color = "#F48FB1",  
    linewidth = 1.2
  ) +
  facet_wrap(~ Mata_Pelajaran, scales = "free", ncol = 3) +
  labs(
    title = "Scatter Plot Hubungan Nilai dan Ketidakhadiran per Mata Pelajaran",
    subtitle = paste("Perbandingan tiap nilai dengan variabel acuan:", y_var),
    x = "Nilai Mata Pelajaran",
    y = "Jumlah Hari Ketidakhadiran"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.background = element_rect(fill = "#FFF8F3", color = NA), 
    panel.background = element_rect(fill = "#FFFFFF", color = NA),
    panel.grid.major = element_line(color = "#F0E6EF"),
    panel.grid.minor = element_blank(),
    strip.background = element_rect(fill = "#E0BBE4", color = NA),
    strip.text = element_text(size = 12, face = "bold", color = "#4B4453"),
    plot.title = element_text(face = "bold", color = "#C06C84", size = 18, hjust = 0.5),
    plot.subtitle = element_text(color = "#6C567B", size = 13, hjust = 0.5),
    axis.title = element_text(color = "#4B4453", size = 12),
    axis.text = element_text(color = "#333333", size = 10),
    legend.position = "none"
    )
## `geom_smooth()` using formula = 'y ~ x'

3.6 Line Plot

  • Definisi

    Bagan Garis adalah alat visualisasi data yang menggambarkan bagaimana nilai berubah dalam suatu urutan, biasanya seiring waktu. Bagan ini menghubungkan titik-titik data dengan garis kontinu, sehingga ideal untuk menampilkan tren dan pola dalam data deret waktu (Wickham2016).

  • Aturan Penggunaan

    1. Dipakai untuk menunjukkan perubahan data dari waktu ke waktu (misalnya penjualan per
      bulan, suhu per hari, pertumbuhan penduduk per tahun).
    2. Sumbu X (horizontal) biasanya berisi waktu atau urutan data.
    3. Sumbu Y (vertikal) berisi nilai yang diukur (misalnya jumlah, suhu, atau nilai).
    4. Titik-titik data dihubungkan dengan garis untuk memperlihatkan arah tren (naik,
      turun, atau stabil).
    5. Gunakan skala yang konsisten supaya garisnya nggak menyesatkan.
    6. Bisa juga menampilkan lebih dari satu garis kalau ingin membandingkan beberapa
      kelompok data.
  • Kelebihan

    1. Mudah melihat tren atau pola perubahan dari waktu ke waktu.
    2. Menunjukkan arah pergerakan data (misalnya naik, turun, atau tetap).
    3. Cocok untuk data berurutan (time series).
    4. Bisa menampilkan beberapa seri data sekaligus untuk dibandingkan.
    5. Sederhana dan mudah dibaca, bahkan oleh orang yang tidak ahli statistik.
  • Kekurangan

    1. Tidak cocok untuk data kategori (misalnya nama kota atau jenis produk).
    2. Kalau data terlalu banyak, garisnya bisa terlalu rapat dan susah dibaca.
    3. Perbedaan kecil antar garis bisa sulit dilihat kalau warnanya mirip.
    4. Tidak terlalu berguna untuk menunjukkan jumlah total atau perbandingan antar
      kategori (lebih cocok pakai bar chart untuk itu).
# Learning Performance Data Visualization (Final & Polished)

# Load Libraries
library(readxl)
library(ggplot2)
library(dplyr)
library(tidyr)

# Read Excel File 
data <- read_excel("kinerja pembelajaran (statistik).xlsx")

# Clean Column Names (safe for R syntax) 
names(data) <- make.names(names(data))

# Select Only Numeric Columns 
numeric_data <- data %>% select(where(is.numeric))

# Soft Pastel Color Palette 
pastel_colors <- c(
  "#A3C4F3", "#FFB6B9", "#FFDAC1", "#E2F0CB",
  "#B5EAD7", "#C7CEEA", "#FFD3B6", "#F6B8B8"
)
pastel_colors <- rep(pastel_colors, length.out = length(unique(names(numeric_data))))


# 1 LINE PLOT: Relationship Between Absence and Scores per Subject
plot_absence <- numeric_data %>%
  pivot_longer(
    cols = -absence.days,
    names_to = "Subject",
    values_to = "Score"
  )

p1 <- ggplot(plot_absence, aes(x = absence.days, y = Score, color = Subject)) +
  geom_line(linewidth = 1.1, alpha = 0.9) +
  geom_point(size = 1.8, alpha = 0.85) +
  scale_color_manual(values = pastel_colors) +
  facet_wrap(~ Subject, scales = "free_y", ncol = 3) +
  labs(
    title = "Relationship Between Absence and Scores per Subject",
    x = "Number of Absence Days",
    y = "Score"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(
      face = "bold",
      color = "#D46A6A",
      size = 15,
      hjust = 0.5,
      vjust = 1.2,
      margin = margin(t = 6, b = 10)
    ),
    strip.background = element_rect(fill = "#FFE6EB", color = NA),
    strip.text = element_text(face = "bold", color = "#4B4453", size = 8.5),
    panel.grid.minor = element_blank(),
    panel.grid.major = element_line(color = "#F2F2F2"),
    panel.spacing = unit(1.1, "lines"),
    axis.title.x = element_text(face = "bold", size = 11, margin = margin(t = 8)),
    axis.title.y = element_text(face = "bold", size = 11, margin = margin(r = 8)),
    plot.background = element_rect(fill = "#FFF8FB", color = NA),
    panel.background = element_rect(fill = "white", color = NA),
    legend.position = "none"
  )

# 2 LINE PLOT: Relationship Between Weekly Study Hours and Scores per Subject
plot_study <- numeric_data %>%
  pivot_longer(
    cols = -weekly_self_study_hours,
    names_to = "Subject",
    values_to = "Score"
  )

p2 <- ggplot(plot_study, aes(x = weekly_self_study_hours, y = Score, color = Subject)) +
  geom_line(linewidth = 1.1, alpha = 0.9) +
  geom_point(size = 1.8, alpha = 0.85) +
  scale_color_manual(values = pastel_colors) +
  facet_wrap(~ Subject, scales = "free_y", ncol = 3) +
  labs(
    title = "Relationship Between Weekly Study Hours and Scores per Subject",
    x = "Weekly Study Hours",
    y = "Score"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    # Main Title: perfectly centered & proportional
    plot.title = element_text(
      face = "bold",
      color = "#6A5ACD",
      size = 14,
      hjust = 0.5,  # precise centering
      vjust = 1.2,
      margin = margin(t = 6, b = 10)
    ),
    # Facet labels smaller to avoid overlap 
    strip.background = element_rect(fill = "#E0BBE4", color = NA),
    strip.text = element_text(face = "bold", color = "#4B4453", size = 8.5),
    panel.grid.minor = element_blank(),
    panel.grid.major = element_line(color = "#F2F2F2"),
    panel.spacing = unit(1.1, "lines"),
    axis.title.x = element_text(face = "bold", size = 11, margin = margin(t = 8)),
    axis.title.y = element_text(face = "bold", size = 11, margin = margin(r = 8)),
    plot.background = element_rect(fill = "#FFF8FB", color = NA),
    panel.background = element_rect(fill = "white", color = NA),
    legend.position = "none"
    )

#view result p1
p1

#view result p2
p2

3.7 Density Plot

  • Definisi

    Density plot atau grafik kepadatan adalah grafik yang digunakan untuk menunjukkan sebaran data numerik (angka) seperti halnya histogram, tetapi bentuknya lebih halus karena menggunakan garis lengkung.

  • Aturan Penggunaan

    1. Gunakan untuk data numerik kontinu (misalnya berat badan, nilai ujian, pendapatan, suhu).
    2. Cocok saat ingin melihat bentuk distribusi data dengan lebih halus dan rapi daripada histogram.
    3. Kalau ingin membandingkan beberapa kelompok, bisa pakai warna berbeda di grafik yang sama.
    4. Gunakan skala yang sama kalau membandingkan lebih dari satu dataset, supaya perbandingan adil.
    5. Tidak cocok untuk data kategori.
  • Kelebihan Density Plot

    1. Menampilkan distribusi data dengan lebih halus dan jelas daripada histogram.
    2. Mudah membaca pola umum, seperti apakah data miring, normal, atau punya dua puncak.
    3. Cocok untuk perbandingan antar kelompok (misalnya nilai laki-laki vs perempuan).
    4. Tidak bergantung pada jumlah atau ukuran “bin” seperti histogram, jadi lebih fleksibel.
    5. Tampilan lebih rapi dan estetis untuk presentasi atau laporan.
  • Kekurangan Density Plot:

    1. Hanya bisa digunakan untuk data numerik kontinu, bukan kategori.
    2. Kurang akurat kalau data sedikit, karena garisnya bisa menipu bentuk distribusi sebenarnya.
    3. Sulit dipahami oleh orang awam, terutama jika belum terbiasa membaca grafik statistik.
    4. Tidak menunjukkan jumlah data secara langsung (karena fokusnya di bentuk sebaran, bukan frekuensi absolut).
    5. Bentuk grafik bisa berubah tergantung pada pengaturan “bandwidth” (tingkat kehalusan garis).
library(ggplot2)
library(dplyr)
library(tidyr)
library(grid)

set.seed(123)
data <- data.frame(
  gender = rep(c("Male", "Female"), each = 100),
  biology_score = rnorm(200, 80, 10),
  chemistry_score = rnorm(200, 82, 9),
  english_score = rnorm(200, 78, 8),
  geography_score = rnorm(200, 81, 9),
  history_score = rnorm(200, 79, 10),
  math_score = rnorm(200, 83, 9),
  physics_score = rnorm(200, 84, 8)
  )

# UBAH DATA KE FORMAT LONG
data_long <- data %>%
  pivot_longer(
    cols = ends_with("_score"),
    names_to = "subject",
    values_to = "score"
    )

pastel_colors <- c("Male" = "#A0C4FF", "Female" = "#FFAFCC")

density_plot <- ggplot(data_long, aes(x = score, fill = gender)) +
  geom_density(alpha = 0.5, color = NA) +
  facet_wrap(~subject, scales = "free", ncol = 3) +
  scale_fill_manual(values = pastel_colors) +
  labs(
    title = "Estimasi Distribusi Probabilitas Nilai Tiap Mata Pelajaran",
    subtitle = "Density plot per mata pelajaran berdasarkan gender",
    x = "Nilai"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    strip.text = element_text(face = "bold", color = "#444444"),
    plot.title = element_text(size = 20, face = "bold", color = "#C2185B", hjust = 0.5),
    plot.subtitle = element_text(size = 14, color = "#7B1FA2", hjust = 0.5),
    axis.title.y = element_blank(),
    axis.title.x = element_text(size = 12, face = "bold"),
    panel.background = element_rect(fill = "#FFF0F5", color = NA),
    plot.background = element_rect(fill = "#FFF0F5", color = NA),
    legend.position = "bottom",
    legend.title = element_blank(),
    legend.text = element_text(size = 11),

# margin kiri lebih kecil supaya label Y lebih dekat
    plot.margin = margin(t = 10, r = 20, b = 10, l = 80)
    )

# TAMPILKAN PLOT DAN LABEL BESAR DI KIRI
    grid.newpage()
    grid.draw(ggplotGrob(density_plot))

# geser teks label Y sedikit ke kanan supaya proporsional
grid.text("Estimasi Distribusi Probabilitas",
          x = unit(0.05, "npc"),  # semula 0.02 → sekarang lebih ke kanan
          y = 0.5,
          rot = 90,
          gp = gpar(fontsize = 14, fontface = "bold", col = "#333333"))

3.8 Ridgeline Plot

  • Definisi

    Ridgeline plot adalah gabungan beberapa density plot (grafik kepadatan) yang ditumpuk secara
    vertikal untuk membandingkan sebaran data dari beberapa kelompok.

  • Aturan Penggunaan

    1. Gunakan untuk data numerik kontinu yang dibagi ke dalam beberapa kelompok atau kategori (contohnya: nilai ujian per tahun, suhu per bulan, pendapatan per provinsi).
    2. Setiap kelompok harus punya jumlah data yang cukup agar bentuk distribusinya jelas.
    3. Urutkan kelompok secara logis (misalnya berdasarkan waktu atau kategori tertentu).
    4. Gunakan warna dan jarak antar lapisan yang konsisten supaya mudah dibaca.
    5. Hindari menumpuk terlalu banyak kelompok, karena bisa jadi berantakan.
  • Kelebihan

    1. Menampilkan banyak distribusi data sekaligus dalam satu grafik.
    2. Mudah membandingkan bentuk dan pergeseran sebaran antar kelompok.
    3. Tampilannya menarik dan estetik, cocok untuk presentasi atau laporan visual.
    4. Membantu menemukan pola tren waktu atau perbedaan antar kategori.
    5. Lebih ringkas dibanding menampilkan banyak histogram atau density plot terpisah.
library(ggplot2)
library(dplyr)
library(tidyr)
library(ggridges)


set.seed(123)
data <- data.frame(
  gender = rep(c("Male", "Female"), each = 100),
  biology_score = rnorm(200, 80, 10),
  chemistry_score = rnorm(200, 82, 9),
  english_score = rnorm(200, 78, 8),
  geography_score = rnorm(200, 81, 9),
  history_score = rnorm(200, 79, 10),
  math_score = rnorm(200, 83, 9),
  physics_score = rnorm(200, 84, 8)
  )

data_long <- data %>%
  pivot_longer(
    cols = ends_with("_score"),
    names_to = "Mata_Pelajaran",
    values_to = "Nilai"
    )

warna_pastel <- c("Male" = "#A0C4FF", "Female" = "#FFAFCC")

ggplot(data_long, aes(x = Nilai, y = Mata_Pelajaran, fill = gender)) +
  geom_density_ridges(alpha = 0.6, color = "white", scale = 1.1, rel_min_height = 0.01) +
  scale_fill_manual(values = warna_pastel) +
  labs(
    title = "Perbandingan Distribusi Beberapa Kelompok",
    subtitle = "Ridgeline plot nilai tiap mata pelajaran berdasarkan gender",
    x = "Nilai",
    y = "Mata Pelajaran"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(size = 18, face = "bold", hjust = 0.5, color = "#C2185B"),
    plot.subtitle = element_text(size = 13, hjust = 0.5, color = "#7B1FA2"),
    axis.title.x = element_text(size = 12, face = "bold"),
    axis.title.y = element_text(size = 12, face = "bold"),
    strip.text = element_text(size = 11, face = "bold"),
    panel.background = element_rect(fill = "#FFF8FB", color = NA),
    plot.background = element_rect(fill = "#FFF8FB", color = NA),
    legend.position = "bottom",
    legend.title = element_blank(),
    legend.text = element_text(size = 11),
    plot.margin = margin(15, 15,15,15)
    )
## Picking joint bandwidth of 3.01

4. Kesimpulan

4.1 Bar Chart – Jumlah Siswa Berdasarkan Gender

  • Visualisasi memperlihatkan bahwa jumlah siswa laki-laki dan perempuan relatif seimbang, tidak ada perbedaan besar di antara keduanya.
  • Kesetaraan komposisi ini memastikan bahwa analisis selanjutnya tidak bias terhadap gender.
  • Artinya, hasil perbandingan nilai atau performa akademik dapat dianggap objektif dan representatif.

4.2 Histogram – Distribusi Nilai per Mata Pelajaran

  • Histogram menunjukkan keragaman pola distribusi nilai antar mata pelajaran.
  • Mata pelajaran seperti Fisika, Matematika, dan Kimia cenderung memiliki nilai terkonsentrasi di rentang tinggi (80–90), menandakan penguasaan konsep yang baik.
  • Sementara Bahasa Inggris dan Sejarah menunjukkan sebaran yang lebih lebar dan bervariasi, menandakan perbedaan kemampuan yang lebih signifikan antar siswa.
  • Insight: beberapa pelajaran mungkin membutuhkan strategi pengajaran berbeda agar semua siswa dapat mencapai performa optimal.

4.3 Boxplot – Perbandingan Nilai Berdasarkan Gender

  • Dari boxplot, terlihat bahwa median nilai siswa laki-laki dan perempuan hampir sama pada semua mata pelajaran.
  • Munculnya outlier menandakan adanya kelompok siswa dengan performa yang jauh di atas atau di bawah rata-rata.
  • Sebaran nilai pada pelajaran sains cenderung lebih besar pada siswa laki-laki, menunjukkan variasi hasil belajar yang lebih lebar.
  • Insight: perbedaan prestasi lebih disebabkan oleh faktor individu dibandingkan faktor gender.

4.4 Pie Chart – Proporsi Gender per Mata Pelajaran

  • Proporsi gender di setiap pelajaran menunjukkan komposisi yang merata.
  • Tidak ada pelajaran yang didominasi oleh satu gender, baik di bidang sains maupun sosial.
  • Hal ini mencerminkan lingkungan belajar yang inklusif dan adil, di mana setiap siswa memiliki kesempatan yang sama untuk berkembang.

4.5 Scatter Plot – Hubungan Antara Nilai dan Absensi

  • Scatter plot menunjukkan pola negatif yang jelas antara jumlah absensi dan nilai.
  • Siswa dengan absensi lebih banyak cenderung memiliki nilai lebih rendah, terutama di pelajaran eksakta (Fisika, Matematika, Kimia).
  • Beberapa pelajaran seperti Bahasa Inggris dan Geografi memperlihatkan hubungan yang lebih
    lemah, mungkin karena sifatnya yang bisa dipelajari secara mandiri.
  • Insight: kehadiran di kelas sangat penting bagi pelajaran yang berbasis latihan dan konsep.

4.6 Line Plot – Tren Hubungan Absensi dan Nilai

  • Line plot memperkuat insight sebelumnya: semakin banyak absen, semakin menurun nilai rata-rata.
  • Penurunan paling signifikan terlihat pada Matematika dan Fisika.
  • Sedangkan pelajaran sosial** relatif lebih stabil, meskipun siswa memiliki tingkat absensi lebih tinggi.
  • Insight: sekolah dapat menggunakan informasi ini untuk meningkatkan kebijakan kehadiran dan membuat sistem peringatan dini bagi siswa yang sering absen.

4.7 Density Plot – Distribusi Nilai Berdasarkan Gender

  • Density plot menunjukkan bahwa laki-laki dan perempuan memiliki distribusi nilai yang hampir identik, artinya performa akademik keduanya relatif sama.
  • Sebagian besar nilai berada di sekitar 80–85, menandakan tingkat pencapaian belajar yang baik secara umum.
  • Beberapa pelajaran menunjukkan dua puncak distribusi (bimodal) ini bisa mengindikasikan adanya kelompok siswa dengan kemampuan yang berbeda (misal: yang memahami materi dan yang masih
    kesulitan).
  • Insight: pembelajaran dapat dipersonalisasi untuk mengakomodasi dua kelompok kemampuan tersebut.

4.8 Ridgeline Plot – Perbandingan Distribusi Beberapa Kelompok

  • Ridgeline plot memberikan gambaran menyeluruh tentang pola sebaran nilai antar pelajaran.
  • Pelajaran seperti Matematika, Kimia, dan Fisika memiliki puncak yang sempit dan tinggi — menunjukkan konsistensi hasil belajar.
  • Sementara Bahasa Inggris dan Sejarah menunjukkan distribusi yang lebih datar, menandakan
    tingkat variasi kemampuan yang lebih besar antar siswa.
  • Insight: kombinasi analisis ini mendukung penerapan strategi belajar diferensial, yaitu menyesuaikan metode pembelajaran dengan karakteristik tiap mata pelajaran.

4.9 Kesimpulan Umum

  1. Kedisiplinan hadir di kelas berpengaruh besar terhadap performa akademik, terutama untuk pelajaran berbasis konsep.
  2. Perbedaan gender tidak memengaruhi performa akademik secara signifikan, menunjukkan lingkungan belajar yang seimbang dan setara.
  3. Variasi hasil belajar antar pelajaran menandakan bahwa pendekatan pembelajaran tidak bisa diseragamkan.
  4. Data menunjukkan pentingnya strategi pengajaran yang fleksibel dan personal, untuk mengatasi perbedaan gaya belajar dan kemampuan siswa.
  5. Secara keseluruhan, kombinasi berbagai visualisasi (bar, histogram, boxplot, scatter, line, density, ridgeline) membantu membangun pemahaman menyeluruh tentang perilaku belajar dan hasil siswa.