1️⃣ Data Sederhana

Ini bisa berupa data simulasi (contoh: skor siswa) yang mudah dimengerti pemula.

data_sederhana <- data.frame(
  Siswa = paste0("Siswa_", 1:10),
  Skor = round(rnorm(10, mean = 75, sd = 5), 1)
)
print(data_sederhana)
##       Siswa Skor
## 1   Siswa_1 79.7
## 2   Siswa_2 77.1
## 3   Siswa_3 67.8
## 4   Siswa_4 73.4
## 5   Siswa_5 67.5
## 6   Siswa_6 71.6
## 7   Siswa_7 74.7
## 8   Siswa_8 74.3
## 9   Siswa_9 71.3
## 10 Siswa_10 76.6

2️⃣ Data Kompleks

Untuk data yang lebih kompleks (misalnya data horsepower), kita bisa gunakan dataset mtcars yang sudah built-in di R (ada kolom hp untuk horsepower). Atau, jika ingin, bisa juga menggunakan dataset dari package ggplot2 atau dari website (misalnya CSV dari UCI Machine Learning Repository). head(data_kompleks) digunakan untuk melihat 6 data awal jika ingin melihat keseluruhan data print(data_kompleks)
Berikut contoh memuat data mtcars (kompleks) dengan analisis horsepower:

data_kompleks <- mtcars
head(data_kompleks)
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

3️⃣ (Opsional) Data Eksternal dari Website

Dataset Diamonds ini diambil dari repositori GitHub seaborn-data, yang sering digunakan untuk demo visualisasi data dan eksplorasi statistik. Dataset ini memuat informasi detail mengenai karakteristik fisik dan harga berbagai jenis berlian.
📌 Sumber Data URL: https://raw.githubusercontent.com/mwaskom/seaborn-data/master/diamonds.csv
Format: CSV (Comma-Separated Values).

📌 Deskripsi Dataset Jumlah Baris (Observasi): ~54.000 baris.
Jumlah Kolom (Variabel): 10 variabel.

📌 Variabel-Variabel Penting carat: Berat berlian (dalam karat).
cut: Kualitas potongan berlian (Fair, Good, Very Good, Premium, Ideal).
color: Grade warna berlian (D terbaik hingga J terburuk).
clarity: Grade kejernihan berlian (IF terbaik hingga I3 terburuk).
depth: Kedalaman total berlian sebagai persentase dari diameter.
table: Lebar permukaan atas berlian (table width).
price: Harga berlian dalam USD.
x: Panjang (mm).
y: Lebar (mm).
z: Tinggi (mm).

📌 Tujuan Dataset
Dataset ini cocok untuk:
✅ Analisis regresi (misalnya: memprediksi harga berlian berdasarkan karat, cut, color, clarity, dll.).
✅ Visualisasi data distribusi dan hubungan antar variabel (boxplot, scatter plot, violin plot).
✅ Eksplorasi multivariat (misalnya clustering, PCA).

load dataset

library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
library(readr)
## Warning: package 'readr' was built under R version 4.3.3
url <- "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/diamonds.csv"
data_eksternal <- read.csv(url)
head(data_eksternal)
##   carat       cut color clarity depth table price    x    y    z
## 1  0.23     Ideal     E     SI2  61.5    55   326 3.95 3.98 2.43
## 2  0.21   Premium     E     SI1  59.8    61   326 3.89 3.84 2.31
## 3  0.23      Good     E     VS1  56.9    65   327 4.05 4.07 2.31
## 4  0.29   Premium     I     VS2  62.4    58   334 4.20 4.23 2.63
## 5  0.31      Good     J     SI2  63.3    58   335 4.34 4.35 2.75
## 6  0.24 Very Good     J    VVS2  62.8    57   336 3.94 3.96 2.48

Langkah 2: cek type data dan Cek Missing Value

str(data_eksternal)
## 'data.frame':    53940 obs. of  10 variables:
##  $ carat  : num  0.23 0.21 0.23 0.29 0.31 0.24 0.24 0.26 0.22 0.23 ...
##  $ cut    : chr  "Ideal" "Premium" "Good" "Premium" ...
##  $ color  : chr  "E" "E" "E" "I" ...
##  $ clarity: chr  "SI2" "SI1" "VS1" "VS2" ...
##  $ depth  : num  61.5 59.8 56.9 62.4 63.3 62.8 62.3 61.9 65.1 59.4 ...
##  $ table  : num  55 61 65 58 58 57 57 55 61 61 ...
##  $ price  : int  326 326 327 334 335 336 336 337 337 338 ...
##  $ x      : num  3.95 3.89 4.05 4.2 4.34 3.94 3.95 4.07 3.87 4 ...
##  $ y      : num  3.98 3.84 4.07 4.23 4.35 3.96 3.98 4.11 3.78 4.05 ...
##  $ z      : num  2.43 2.31 2.31 2.63 2.75 2.48 2.47 2.53 2.49 2.39 ...
colSums(is.na(data_eksternal))
##   carat     cut   color clarity   depth   table   price       x       y       z 
##       0       0       0       0       0       0       0       0       0       0

Langkah 3: Distribusi Data

Histogram Harga Berlian, bins = 50 untuk memperbanyak jumlah barnya

ggplot(data_eksternal, aes(x = price), fill = price) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Distribusi Harga Berlian", x = "Harga (USD)", y = "Frekuensi") +
  theme_minimal()

bins pada geom_histogram()
bins menentukan berapa banyak batang (interval) yang digunakan untuk membagi data pada sumbu X (dalam hal ini, price).

Ini akan mengelompokkan nilai price ke dalam beberapa rentang (bin), kemudian menghitung berapa banyak data yang jatuh dalam setiap bin → untuk membuat histogram.

📌 bins = 10 vs bins = 50
bins = 10 → histogram dengan 10 batang, cocok untuk overview distribusi secara kasar.
bins = 50 → histogram dengan 50 batang, lebih detail sehingga distribusi lebih halus dan granular.

📌 Kapan Pakai Berapa Bins?
✅ Gunakan bins lebih kecil (10–20) untuk overview kasar distribusi data.
✅ Gunakan bins lebih besar (50 atau lebih) untuk melihat pola distribusi lebih detail, terutama kalau datasetnya besar.

Density Plot Karat

ggplot(data_eksternal, aes(x = carat)) +
  geom_density(fill = "lightgreen", alpha = 0.5) +
  labs(title = "Distribusi Berat Berlian (carat)", x = "Carat", y = "Density") +
  theme_minimal()

menampilkan density untuk carat dan price.
Karena keduanya numerik dan memiliki skala berbeda, biasanya kita perlu:
✅ Membuat dataframe dalam format long (pivot_longer).
✅ Plot density dengan warna berbeda per variabel.

📌 Membandingkan Dua Variabel Numerik
Misalnya, kamu ingin menampilkan density untuk carat dan price.
Karena keduanya numerik dan memiliki skala berbeda, biasanya kita perlu:
✅ Membuat dataframe dalam format long (pivot_longer).
✅ Plot density dengan warna berbeda per variabel.

library(tidyverse)
data_long <- data_eksternal %>%
  select(carat, price) %>%
  mutate(price = log10(price + 1)) %>%   # transformasi log agar skala price lebih kecil
  pivot_longer(cols = everything(), names_to = "Variable", values_to = "Value")

ggplot(data_long, aes(x = Value, fill = Variable)) +
  geom_density(alpha = 0.5) +
  labs(title = "Distribusi Carat dan log(Price)", x = "Value", y = "Density") +
  theme_minimal()

data_long <- data_eksternal %>%
  select(carat, price) %>%
  pivot_longer(cols = everything(), names_to = "Variable", values_to = "Value")

ggplot(data_long, aes(x = Value, fill = Variable)) +
  geom_density(alpha = 0.5) +
  facet_wrap(~Variable, scales = "free") +
  labs(title = "Distribusi Carat dan Price", x = "Value", y = "Density") +
  theme_minimal()

Membandingkan Distribusi Satu Variabel di Dua Kelompok Misalnya, kamu ingin membandingkan distribusi carat di dua cut: “Ideal” dan “Premium”:

ggplot(filter(data_eksternal, cut %in% c("Ideal", "Premium")), 
       aes(x = carat, fill = cut)) +
  geom_density(alpha = 0.5) +
  labs(title = "Distribusi Carat berdasarkan Cut", x = "Carat", y = "Density") +
  theme_minimal()

  1. Bentuk Distribusi
    Puncak tertinggi (mode) terlihat di karat sekitar 0.3–0.5.

Kedua distribusi menunjukkan pola distribusi positively skewed (memiliki ekor panjang ke kanan). Artinya, sebagian besar berlian memiliki karat kecil, sedangkan yang besar lebih jarang.

📌 2. Perbandingan Distribusi
Ideal (pink):
Lebih banyak pada karat rendah (sekitar 0.3–0.5).
Density-nya tinggi, artinya mayoritas berlian dengan cut Ideal memiliki karat rendah.
Premium (biru):
Distribusinya juga terkonsentrasi di karat rendah (0.3–0.5), tetapi lebih lebar (sedikit lebih banyak di sekitar 1).
Ada lebih banyak variasi karat, termasuk karat lebih tinggi (sekitar 1–2).

📌 3. Overlap Area pink (Ideal) dan biru (Premium) overlap cukup banyak pada karat rendah (sekitar 0.3–0.5).
Pada karat lebih tinggi (di atas 1), Premium mendominasi (lebih banyak berlian Premium daripada Ideal).

📌 4. Kesimpulan Sebagian besar berlian (Ideal dan Premium) memiliki karat rendah.
Premium cenderung memiliki rentang karat lebih luas dibandingkan Ideal.
Visualisasi ini membantu memahami bagaimana distribusi karat bervariasi antar jenis cut.

Scatter Plot (Karat vs Harga)

ggplot(data_eksternal, aes(x = carat, y = price)) +
  geom_point(alpha = 0.3, color = "darkblue") +
  labs(title = "Scatter Plot Karat vs Harga Berlian", x = "Carat", y = "Harga (USD)") +
  theme_minimal()

Scatter Plot dengan Garis Regresi

ggplot(data_eksternal, aes(x = carat, y = price)) +
  geom_point(alpha = 0.3, color = "darkblue") +
  geom_smooth(method = "lm", color = "red", se = TRUE) +
  labs(title = "Scatter Plot Karat vs Harga dengan Regresi", x = "Carat", y = "Harga (USD)") +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

memperkecil skala pada y yakni menggunakan ylim jika ingin pada x maka xlim

ggplot(data_eksternal, aes(x = carat, y = price)) +
  geom_point(alpha = 0.3, color = "darkblue") +
  geom_smooth(method = "lm", color = "red", se = TRUE) +
  labs(title = "Scatter Plot Karat vs Harga dengan Regresi", x = "Carat", y = "Harga (USD)") +
  ylim(0, 20000) +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 38 rows containing missing values or values outside the scale range
## (`geom_smooth()`).

melihat rata-rata harga berlian per cut dan clarity

library(dplyr)
summary_data <- data_eksternal %>%
  group_by(cut, clarity) %>%
  summarise(mean_price = mean(price))
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
ggplot(summary_data, aes(x = cut, y = mean_price, fill = clarity)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(title = "Rata-rata Harga Berlian per Cut dan Clarity",
       x = "Cut", y = "Rata-rata Harga (USD)") +
  theme_minimal()

📌 1️⃣ stat = “identity”
Biasanya, geom_bar() digunakan untuk count/frequency plot (barplot default) — misalnya menghitung banyaknya data per kategori. Dalam hal ini, ggplot akan menghitung frekuensi data secara otomatis.

📌 2️⃣ position = “dodge”
Karena kamu ingin membandingkan mean_price per cut dan clarity dalam satu plot:
✅ fill = clarity membuat bar dibagi warna sesuai clarity.
✅ position = “dodge” memberitahu ggplot untuk menampilkan bar clarity berdampingan secara horizontal dalam satu cut.

👉 Tanpa position = “dodge”, default-nya akan menumpuk (stacked bar).

library(dplyr)
summary_data <- data_eksternal %>%
  group_by(cut, clarity) %>%
  summarise(mean_price = mean(price))
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
ggplot(summary_data, aes(x = cut, y = mean_price, fill = clarity)) +
  geom_bar(stat = "identity") +
  labs(title = "Rata-rata Harga Berlian per Cut dan Clarity",
       x = "Cut", y = "Rata-rata Harga (USD)") +
  theme_minimal()

📌 Kesimpulan
👉 Kalau kamu hanya menggunakan satu warna fill (misalnya “green”), tidak ada kategori yang harus di-dodge, sehingga position = “dodge” tidak berpengaruh.
👉 Kalau kamu ingin dodge aktif, gunakan fill = clarity agar bar clarity muncul berdampingan.

ggplot(summary_data, aes(x = cut, y = mean_price, fill = clarity)) +
  geom_bar(stat = "identity", position = "dodge", color = "black") +
  labs(title = "Rata-rata Harga Berlian per Cut dan Clarity",
       x = "Cut", y = "Rata-rata Harga (USD)") +
  theme_minimal()

## Plot horizontal bar chart

library(dplyr)
library(ggplot2)

# Hitung rata-rata harga berlian per Cut dan Clarity
summary_data <- data_eksternal %>%
  group_by(cut, clarity) %>%
  summarise(mean_price = mean(price))
## `summarise()` has grouped output by 'cut'. You can override using the `.groups`
## argument.
ggplot(summary_data, aes(x = mean_price, y = reorder(cut, mean_price), fill = clarity)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(title = "Rata-rata Harga Berlian per Cut dan Clarity",
       x = "Rata-rata Harga (USD)",
       y = "Cut") +
  theme_minimal()

barplot

summary_data <- data_eksternal %>%
  group_by(cut) %>%
  summarise(mean_price = mean(price))

ggplot(summary_data, aes(x = reorder(cut, mean_price), y = mean_price, fill = cut)) +
  geom_bar(stat = "identity") +
  labs(title = "Rata-rata Harga Berlian per Cut",
       x = "Cut", y = "Rata-rata Harga (USD)") +
  theme_minimal()

summary_data <- data_eksternal %>%
  group_by(cut) %>%
  summarise(mean_price = mean(price))

ggplot(summary_data, aes(x = reorder(cut, mean_price), y = mean_price)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  labs(title = "Rata-rata Harga Berlian per Cut",
       x = "Cut", y = "Rata-rata Harga (USD)") +
  theme_minimal()

Secara default, reorder(cut, mean_price) akan mengurutkan dari nilai mean_price terkecil ke terbesar (ascending).
Kalau kamu ingin dari besar ke kecil (descending), cukup tambahkan tanda minus (-) di depan mean_price di dalam reorder().

ggplot(summary_data, aes(x = reorder(cut, -mean_price), y = mean_price)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  labs(title = "Rata-rata Harga Berlian per Cut",
       x = "Cut", y = "Rata-rata Harga (USD)") +
  theme_minimal()

Plot side bar chart (horizontal)

library(dplyr)
library(ggplot2)

# Ringkas data
summary_data <- data_eksternal %>%
  group_by(cut) %>%
  summarise(mean_price = mean(price))

ggplot(summary_data, aes(x = mean_price, y = reorder(cut, mean_price))) +
  geom_bar(stat = "identity", fill = "steelblue") +
  labs(title = "Rata-rata Harga Berlian per Cut",
       x = "Rata-rata Harga (USD)", y = "Cut") +
  theme_minimal()

Plot Density Berdasarkan Cut

ggplot(data_eksternal, aes(x = price, fill = cut)) +
  geom_density(alpha = 0.5) +
  labs(title = "Distribusi Harga Berlian per Cut",
       x = "Harga (USD)", y = "Density") +
  theme_minimal()

Boxplot per Cut

ggplot(data_eksternal, aes(x = cut, y = price, fill = cut)) +
  geom_boxplot() +
  labs(title = "Boxplot Harga Berlian per Cut",
       x = "Cut", y = "Harga (USD)") +
  theme_minimal()

Violin Plot

ggplot(data_eksternal, aes(x = cut, y = price, fill = cut)) +
  geom_violin() +
  labs(title = "Violin Plot Harga Berlian per Cut",
       x = "Cut", y = "Harga (USD)") +
  theme_minimal()

Violin plot menunjukkan distribusi Harga (USD) berlian untuk setiap kategori Cut (Fair, Good, Ideal, Premium, Very Good) dengan bentuk yang lebih detail daripada boxplot.
🔍 Gambaran Umum
Lebar Violin
Semakin lebar violin di suatu titik, semakin tinggi kepadatan (density) harga berlian di rentang harga tersebut.
Fair cenderung memiliki sebaran harga di kisaran 0-5000 USD dengan beberapa kepadatan tinggi di sekitar 2000-3000 USD.

Rentang Harga
Semua kategori Cut memiliki rentang harga yang sangat lebar (hingga 20000 USD lebih).
Namun, distribusi terpadat cenderung terjadi di kisaran rendah (0-5000 USD).

Outlier
Violin plot secara default tidak menunjukkan outlier seperti boxplot, tetapi rentang distribusi panjang ke atas menunjukkan potensi harga tinggi (meskipun frekuensi rendah).

Perbandingan antar Cut
Semua Cut memiliki bentuk violin yang cukup mirip (seperti lonceng yang tinggi dan ramping), menandakan pola distribusi yang konsisten (harga rendah lebih sering, harga tinggi lebih jarang).
Premium dan Very Good cenderung sedikit lebih lebar di bagian bawah, artinya banyak berlian dengan harga lebih rendah pada Cut ini.

📌 Insight
✅ Berlian cenderung memiliki harga yang paling sering di kisaran 0-5000 USD.
✅ Semua Cut menunjukkan distribusi harga yang mirip, dengan ekor panjang ke atas (skewed).
✅ Violin plot membantu menunjukkan bentuk distribusi (positively skewed) dibandingkan boxplot yang hanya menampilkan ringkasan.
✅ Tidak ada Cut yang dominan memiliki harga tinggi secara konsisten.

library(GGally)
## Warning: package 'GGally' was built under R version 4.3.2
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
ggpairs(data_eksternal[, c("price", "carat", "depth", "table")])

## # Plot heatmap

library(ggplot2)
library(reshape2)
## 
## Attaching package: 'reshape2'
## The following object is masked from 'package:tidyr':
## 
##     smiths
library(dplyr)

# Pilih variabel numerik saja
numerik_data <- data_eksternal %>% select_if(is.numeric)

# Hitung korelasi
cor_matrix <- cor(numerik_data, use = "complete.obs")

# Ubah matrix ke format long (melt)
melted_cor <- melt(cor_matrix)

ggplot(melted_cor, aes(x = Var1, y = Var2, fill = value)) +
  geom_tile(color = "white") +
  scale_fill_gradient2(low = "red", high = "blue", mid = "white",
                       midpoint = 0, limit = c(-1,1), name = "Korelasi") +
  theme_minimal() +
  labs(title = "Heatmap Korelasi Variabel Numerik",
       x = "Variabel", y = "Variabel") +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1))

Plot heatmap dengan label angka

library(ggplot2)
library(reshape2)
ggplot(melted_cor, aes(x = Var1, y = Var2, fill = value)) +
  geom_tile(color = "white") +
  geom_text(aes(label = round(value, 2)), size = 3) +  # Tambahkan angka di tengah kotak
  scale_fill_gradient2(low = "red", high = "blue", mid = "white",
                       midpoint = 0, limit = c(-1,1), name = "Korelasi") +
  theme_minimal() +
  labs(title = "Heatmap Korelasi Variabel Numerik",
       x = "Variabel", y = "Variabel") +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1))