Setelah memahami pola distribusi satu variabel, analisis dapat dilanjutkan ke tahap berikutnya, yaitu visualisasi bivariate. Visualisasi bivariate digunakan untuk melihat hubungan antara dua variabel, misalnya bagaimana jumlah penyewaan sepeda (cnt) dipengaruhi oleh faktor lain seperti musim (season), kondisi cuaca (weathersit), suhu (temp), atau jenis hari (workingday). Pendekatan ini memungkinkan analis tidak hanya memahami bagaimana data tersebar, tetapi juga mulai mengeksplorasi faktor-faktor yang berasosiasi dengan perubahan jumlah penyewaan sepeda.
Dengan demikian, visualisasi univariate memberikan pemahaman awal mengenai karakteristik dan variasi data, sedangkan visualisasi bivariate membantu menggali hubungan antarvariabel yang dapat menjelaskan pola penggunaan sepeda secara lebih mendalam.
Dataset ini berasal dari sistem bike sharing di Washington, D.C., yang diperoleh dari UCI Machine Learning Repository . Dataset ini mencatat aktivitas penyewaan sepeda setiap hari selama dua tahun. Setelah memahami dalam kondisi apa data dikumpulkan (musim, cuaca, dan jenis hari), langkah berikutnya adalah melihat bagaimana perilaku nilai numerik dalam dataset.
Import data dari file CSV ke dalam R menggunakan fungsi read.csv(). Pastikan untuk menyesuaikan path file dengan lokasi di mana dataset disimpan di komputer Anda. Berikut adalah kode untuk memuat data:
# 1. Bersihkan data lama
rm(list = ls(all.names = TRUE)) # Hapus semua termasuk hidden objects
gc() # Paksa garbage collection
## used (Mb) gc trigger (Mb) max used (Mb)
## Ncells 1072574 57.3 2163472 115.6 1451022 77.5
## Vcells 1888750 14.5 8388608 64.0 3199546 24.5
invisible(gc()) # Double garbage collection
cat("\014") # Bersihkan console
# 2. LOAD LIBRARY
library(ggplot2)
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.5.1
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
# 3. FUNGSI KHUSUS UNTUK BACA DATA DENGAN PAKSAAN FORMAT
baca_data_stabil <- function(file_path) {
# Baca sebagai data frame biasa
df <- read.csv(file_path, sep = ";", header = TRUE, stringsAsFactors = FALSE)
# PAKSA semua kolom kategorik menjadi character dulu
df$season <- as.character(df$season)
df$weathersit <- as.character(df$weathersit)
df$holiday <- as.character(df$holiday)
df$workingday <- as.character(df$workingday)
# Konversi ke faktor dengan LEVEL YANG DIKUNCI
df$season <- factor(df$season,
levels = c("1", "2", "3", "4"),
labels = c("Spring", "Summer", "Fall", "Winter"),
ordered = FALSE)
df$weathersit <- factor(df$weathersit,
levels = c("1", "2", "3"),
labels = c("Clear", "Cloudy", "Light Rain"),
ordered = FALSE)
df$holiday <- factor(df$holiday,
levels = c("0", "1"),
labels = c("No", "Yes"),
ordered = FALSE)
df$workingday <- factor(df$workingday,
levels = c("0", "1"),
labels = c("No", "Yes"),
ordered = FALSE)
# VERIFIKASI: Cetak struktur
cat("\n=== VERIFIKASI STRUKTUR DATA ===\n")
cat("Class weathersit:", class(df$weathersit), "\n")
cat("Levels weathersit:", paste(levels(df$weathersit), collapse = ", "), "\n")
cat("\nDistribusi weathersit:\n")
print(table(df$weathersit))
return(df)
}
# 4. BACA DATA DENGAN FUNGSI SUPER STABIL
cat("MEMBACA DATA...\n")
## MEMBACA DATA...
bike_data <- baca_data_stabil("databike/bikesharingdatasetby-day.csv")
##
## === VERIFIKASI STRUKTUR DATA ===
## Class weathersit: factor
## Levels weathersit: Clear, Cloudy, Light Rain
##
## Distribusi weathersit:
##
## Clear Cloudy Light Rain
## 463 247 21
# 5. CEK ULANG DENGAN CARA BERBEDA (DOUBLE CHECK)
cat("\n=== DOUBLE CHECK ===\n")
##
## === DOUBLE CHECK ===
cat("Jumlah data:", nrow(bike_data), "baris\n")
## Jumlah data: 731 baris
cat("Apakah weathersit factor?", is.factor(bike_data$weathersit), "\n")
## Apakah weathersit factor? TRUE
cat("Jumlah per kategori:\n")
## Jumlah per kategori:
print(sapply(levels(bike_data$weathersit), function(lvl) {
sum(bike_data$weathersit == lvl, na.rm = TRUE)
}))
## Clear Cloudy Light Rain
## 463 247 21
colnames(bike_data)
## [1] "instant" "dteday" "season" "yr" "mnth"
## [6] "holiday" "weekday" "workingday" "weathersit" "temp"
## [11] "atemp" "hum" "windspeed" "casual" "registered"
## [16] "cnt"
Berdasarkan output di atas, dataset ini memiliki 16 variabel, termasuk variabel numerik dan kategorik. Variabel numerik dalam dataset ini termasuk temp, atemp, hum, windspeed, casual, registered, dan cnt. Variabel-variabel ini memberikan informasi tentang suhu, kelembapan, kecepatan angin, jumlah penyewaan sepeda oleh pengguna kasual, jumlah penyewaan sepeda oleh pengguna terdaftar, dan total jumlah penyewaan sepeda. Berikut adalah deskripsi dari variabel-variabel numerik dalam dataset:
Sedangkan variabel-variabel kategorik sudah dijelaskan pembelajaran sebelumnya, variabel-variabel kategorik seperti season, weathersit, dan workingday di-recode untuk memudahkan dalam interpretasi visualisasi dan analisis selanjutnya.
Dengan melakukan recode pada variabel-variabel kategorik, kita dapat lebih mudah memahami dan menginterpretasikan visualisasi yang akan dibuat selanjutnya. Misalnya, ketika kita membuat grafik yang menunjukkan jumlah penyewaan sepeda berdasarkan musim, kita dapat langsung melihat label “Spring”, “Summer”, “Fall”, dan “Winter” daripada harus mengingat bahwa 1 = Spring, 2 = Summer, dan seterusnya. Hal ini membuat visualisasi lebih intuitif dan mudah dipahami oleh audiens.
Struktur data setelah recode akan tetap sama, tetapi nilai-nilai dalam variabel season, weathersit, dan workingday sekarang memiliki label yang lebih deskriptif. Ini akan memudahkan kita dalam membuat visualisasi yang lebih informatif dan mudah dipahami.
datatable(bike_data, options = list(pageLength = 5, autoWidth = TRUE))
Setelah memahami pola distribusi satu variabel, analisis dapat dilanjutkan ke tahap berikutnya, yaitu visualisasi bivariate. Visualisasi bivariate digunakan untuk melihat hubungan antara dua variabel, misalnya bagaimana jumlah penyewaan sepeda (cnt) dipengaruhi oleh faktor lain seperti musim (season), kondisi cuaca (weathersit), suhu (temp), atau jenis hari (workingday). Pendekatan ini memungkinkan analis tidak hanya memahami bagaimana data tersebar, tetapi juga mulai mengeksplorasi faktor-faktor yang berasosiasi dengan perubahan jumlah penyewaan sepeda.
]Berikut adalah beberapa jenis visualisasi bivariate yang dapat digunakan untuk menganalisis hubungan antara jumlah penyewaan sepeda (cnt) dengan variabel lain dalam dataset:
Scatter plot adalah grafik yang menunjukkan hubungan antara dua variabel numerik. Setiap titik pada scatter plot mewakili satu pengamatan, dengan posisi titik ditentukan oleh nilai kedua variabel. Berikut adalah contoh kode untuk membuat scatter plot antara cnt dan temp:
ggplot(bike_data, aes(x = temp, y = cnt)) +
geom_point(color = "steelblue", alpha = 0.5) +
labs(title = "Scatter Plot of Total Bike Rentals vs Temperature",
x = "Temperature (temp)",
y = "Total Rentals (cnt)") +
theme_minimal()
Scatter plot di atas menunjukkan hubungan antara suhu (temp) dan jumlah penyewaan sepeda (cnt). Setiap titik pada grafik mewakili satu hari, dengan posisi horizontal menunjukkan suhu dan posisi vertikal menunjukkan jumlah penyewaan sepeda pada hari tersebut. Dari visualisasi ini terlihat bahwa terdapat pola positif antara suhu dan jumlah penyewaan sepeda, di mana semakin tinggi suhu, semakin banyak penyewaan sepeda yang terjadi. Hal ini menunjukkan bahwa cuaca yang lebih hangat cenderung meningkatkan penggunaan sepeda, sementara suhu yang lebih rendah mungkin membuat orang enggan untuk menyewa sepeda. Meskipun terdapat beberapa titik yang menyebar, pola umum menunjukkan bahwa suhu memiliki pengaruh positif terhadap jumlah penyewaan sepeda.
Boxplot bivariate digunakan untuk membandingkan distribusi variabel numerik (cnt) berdasarkan kategori dari variabel lain, seperti musim (season). Berikut adalah contoh kode untuk membuat boxplot bivariate antara cnt dan season:
ggplot(bike_data, aes(x = season, y = cnt)) +
geom_boxplot(fill = "lightblue", color = "darkblue") +
labs(title = "Boxplot of Total Bike Rentals by Musim",
x = "Musim",
y = "Total Rentals (cnt)") +
theme_minimal()
Boxplot bivariate di atas digunakan untuk membandingkan distribusi jumlah penyewaan sepeda (cnt) berdasarkan kategori musim (season). Setiap kotak pada grafik mewakili distribusi penyewaan sepeda untuk masing-masing musim, dengan garis di dalam kotak menunjukkan median, batas kotak menunjukkan kuartil pertama (Q1) dan kuartil ketiga (Q3), serta whisker yang memanjang menunjukkan rentang data. Dari visualisasi ini terlihat bahwa musim Summer memiliki jumlah penyewaan sepeda yang lebih tinggi dibandingkan dengan musim lainnya, dengan median yang berada di kisaran 5.000 penyewaan per hari. Sementara itu, musim Winter memiliki jumlah penyewaan yang lebih rendah, dengan median di bawah 3.000 penyewaan per hari. Hal ini menunjukkan bahwa penggunaan sepeda cenderung meningkat selama musim panas dan menurun selama musim dingin, kemungkinan karena faktor cuaca yang mempengaruhi kenyamanan dalam menggunakan sepeda.
Violin plot bivariate digunakan untuk membandingkan distribusi variabel numerik (cnt) berdasarkan kategori dari variabel lain, seperti kondisi cuaca (weathersit). Berikut adalah contoh kode untuk membuat violin plot bivariate antara cnt dan weathersit:
ggplot(bike_data, aes(x = weathersit, y = cnt)) +
geom_violin(fill = "lightcoral", color = "darkred", alpha = 0.6) +
geom_boxplot(width = 0.1, fill = "white", color = "black", outlier.shape = NA) +
labs(title = "Violin Plot of Total Bike Rentals by Kondisi Cuaca",
x = "Kondisi Cuaca",
y = "Total Rentals (cnt)") +
theme_minimal()
Violin plot bivariate di atas digunakan untuk membandingkan distribusi jumlah penyewaan sepeda (cnt) berdasarkan kondisi cuaca (weathersit). Setiap bentuk violin mewakili distribusi penyewaan sepeda untuk masing-masing kondisi cuaca, dengan bagian yang lebih lebar menunjukkan bahwa lebih banyak hari memiliki jumlah penyewaan pada kisaran tersebut. Boxplot di dalam violin memberikan informasi statistik ringkas, seperti median dan kuartil. Dari visualisasi ini terlihat bahwa kondisi cuaca yang cerah (Clear) memiliki distribusi penyewaan sepeda yang lebih tinggi dan lebih padat dibandingkan dengan kondisi cuaca lainnya, seperti hujan ringan (Light Rain) atau hujan deras (Heavy Rain), yang memiliki distribusi penyewaan yang lebih rendah. Hal ini menunjukkan bahwa kondisi cuaca yang baik cenderung meningkatkan penggunaan sepeda, sementara kondisi cuaca yang buruk dapat mengurangi minat orang untuk menyewa sepeda.
# Ambil sampel 300 data untuk bubble plot agar tidak terlalu penuh
set.seed(123)
bike_sample <- bike_data[sample(nrow(bike_data), 300), ]
ggplot(bike_sample, aes(x = temp, y = windspeed, size = cnt, color = cnt)) +
geom_point(alpha = 0.7) +
scale_size_continuous(range = c(1, 12), name = "Jumlah Sewa") +
scale_color_gradient(low = "blue", high = "red", name = "Jumlah Sewa") +
labs(title = "Bubble Plot: Pengaruh Suhu dan Kecepatan Angin terhadap Penyewaan Sepeda",
x = "Suhu (°C)",
y = "Kecepatan Angin") +
theme_minimal()
Bubble plot ini menjawab pertanyaan “Apakah suhu dan kecepatan angin berpengaruh terhadap jumlah penyewaan sepeda?” dengan menunjukkan bahwa kombinasi kedua faktor tersebut sangat menentukan tinggi rendahnya penyewaan. Bubble dengan ukuran besar (warna merah) yang merepresentasikan jumlah penyewaan tinggi (>5000 unit) terkonsentrasi pada area dengan suhu 20-30°C dan kecepatan angin rendah di bawah 15 km/jam. Sebaliknya, ketika kecepatan angin meningkat di atas 20 km/jam, ukuran bubble mengecil secara konsisten meskipun suhu berada dalam rentang optimal, mengindikasikan bahwa angin kencang menjadi faktor penghambat utama. Pola ini menegaskan bahwa penyewaan sepeda mencapai puncaknya pada kondisi “ideal” yaitu suhu hangat dengan angin tenang, sementara kondisi di luar itu cenderung menurunkan minat penyewa.
library(dplyr)
# Hitung rata-rata penyewaan per bulan
monthly_avg <- bike_data %>%
group_by(mnth) %>%
summarise(avg_cnt = mean(cnt, na.rm = TRUE))
# Buat label bulan
monthly_avg$month_name <- factor(month.abb[monthly_avg$mnth], levels = month.abb)
ggplot(monthly_avg, aes(x = month_name, y = avg_cnt, group = 1)) +
geom_line(color = "darkblue", size = 1.2) +
geom_point(color = "red", size = 3) +
labs(title = "Line Plot: Tren Rata-rata Penyewaan Sepeda per Bulan",
x = "Bulan",
y = "Rata-rata Jumlah Penyewaan (cnt)") +
theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Line plot ini menjawab pertanyaan “Bagaimana tren penyewaan sepeda
sepanjang bulan dalam setahun?” dengan memperlihatkan pola musiman yang
sangat jelas berbentuk seperti lonceng. Tren dimulai dari titik terendah
di bulan Januari-Februari (musim dingin), kemudian meningkat secara
konsisten hingga mencapai puncak pada bulan Juni-September (musim
panas), sebelum akhirnya menurun drastis kembali menuju akhir tahun.
Puncak penyewaan terjadi di bulan Juli-Agustus dengan rata-rata di atas
6000 unit, sementara palung terendah di bulan Desember-Januari dengan
rata-rata di bawah 2000 unit. Pola ini mengkonfirmasi bahwa penyewaan
sepeda sangat dipengaruhi oleh siklus iklim tahunan, dengan aktivitas
tertinggi terjadi pada bulan-bulan hangat yang nyaman untuk bersepeda,
dan terendah pada bulan-bulan dingin yang tidak mendukung aktivitas
outdoor.
ggplot(bike_data, aes(x = temp, y = hum)) +
stat_density_2d(aes(fill = after_stat(density)), geom = "raster", contour = FALSE, alpha = 0.8) +
scale_fill_gradientn(colors = c("white", "lightyellow", "orange", "red", "darkred")) +
geom_density_2d(color = "black", alpha = 0.5, linewidth = 0.3) +
labs(title = "2D Density Plot: Distribusi Bersama Suhu dan Kelembaban",
x = "Suhu (°C)",
y = "Kelembaban (%)") +
theme_minimal() +
theme(legend.position = "none")
2D density plot ini menjawab pertanyaan “Di mana pusat massa distribusi bersama suhu dan kelembaban berada?” dengan memvisualisasikan area dengan konsentrasi data tertinggi. Pusat massa (area berwarna merah tua hingga darkred) teridentifikasi berada pada rentang suhu 20-28°C dan kelembaban 40-70%, yang merupakan kondisi lingkungan paling sering terjadi dalam dataset. Garis kontur hitam membagi area berdasarkan level kepadatan, dengan kontur paling dalam menunjukkan zona dengan frekuensi observasi tertinggi. Pola distribusi membentuk gumpalan elips yang memanjang, mengindikasikan bahwa sebagian besar data terkonsentrasi di zona nyaman tersebut, sementara area di luar itu (suhu ekstrem atau kelembaban sangat tinggi) memiliki kepadatan yang jauh lebih rendah. Visualisasi ini penting untuk memahami bahwa operasional penyewaan sepeda sebagian besar berlangsung pada kondisi lingkungan yang relatif homogen dan nyaman.