Nomor 1 & 2

Data yang akan digunakan dalam praktik Data Visualization (khusus untuk case no. 1 dan 2) adalah data Youtube’s US Trending Videos.

Contoh trending video di Youtube (https://www.youtube.com/feed/trending):

Read Data

# Read data, masukkan ke object vids, lihat 6 baris teratas
vids <- read.csv("data_input/USvideos.csv")
head(vids)

Deskripsi 12 kolom pada dataframe:

  • trending_date: tanggal trending (format: YY.DD.MM)
  • title: judul video
  • channel_title: nama channel Youtube
  • category_id: kategori video
  • publish_time: tanggal upload video (format: YYYY-MM-DD-HH-MM-SS)
  • views: jumlah views dalam video tersebut
  • likes: jumlah likes dalam video tersebut
  • dislikes: jumlah dislikes dalam video tersebut
  • comment_count jumlah komentar
  • comment_disabled: apakah kolom komentar tidak diaktifkan
  • rating_disabled: apakah rating video tidak diaktifkan
  • video_error_or_removed: apakah video sudah dihapus

Lakukan inspeksi tipe data, untuk memastikan tipe data sudah sesuai.

# Inspect Data Type 
str(vids)
#> 'data.frame':    13400 obs. of  12 variables:
#>  $ trending_date         : chr  "17.14.11" "17.14.11" "17.14.11" "17.14.11" ...
#>  $ title                 : chr  "WE WANT TO TALK ABOUT OUR MARRIAGE" "The Trump Presidency: Last Week Tonight with John Oliver (HBO)" "Racist Superman | Rudy Mancuso, King Bach & Lele Pons" "Nickelback Lyrics: Real or Fake?" ...
#>  $ channel_title         : chr  "CaseyNeistat" "LastWeekTonight" "Rudy Mancuso" "Good Mythical Morning" ...
#>  $ category_id           : int  22 24 23 24 24 28 24 28 1 25 ...
#>  $ publish_time          : chr  "2017-11-13T17:13:01.000Z" "2017-11-13T07:30:00.000Z" "2017-11-12T19:05:24.000Z" "2017-11-13T11:00:04.000Z" ...
#>  $ views                 : int  748374 2418783 3191434 343168 2095731 119180 2103417 817732 826059 256426 ...
#>  $ likes                 : int  57527 97185 146033 10172 132235 9763 15993 23663 3543 12654 ...
#>  $ dislikes              : int  2966 6146 5339 666 1989 511 2445 778 119 1363 ...
#>  $ comment_count         : int  15954 12703 8181 2146 17518 1434 1970 3432 340 2368 ...
#>  $ comments_disabled     : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
#>  $ ratings_disabled      : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
#>  $ video_error_or_removed: logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
unique(vids$category_id)
#>  [1] 22 24 23 28  1 25 17 10 15 27 26  2 19 20 29 43
colSums(is.na(vids))
#>          trending_date                  title          channel_title 
#>                      0                      0                      0 
#>            category_id           publish_time                  views 
#>                      0                      0                      0 
#>                  likes               dislikes          comment_count 
#>                      0                      0                      0 
#>      comments_disabled       ratings_disabled video_error_or_removed 
#>                      0                      0                      0

Apa saja kolom yang tipe datanya belum sesuai?

  • publish_time –> date
  • trending_date –> date
  • category_id –> factor

Kenapa melakukan inspeksi tipe data itu penting sebelum melanjutkan ke tahap selanjutnya? Untuk memastikan bahwa semua tipe data yang ada pada dataframe tersebut sudah sesuai dan bisa diolah lebih lanjut.

Data Wrangling

Manipulasi data waktu menggunakan fungsi as.Date()

Syntax: as.Date(x = df$kolom, format)

Default format: Year - Month - Day (YYYY/MM/DD atau YYYY-MM-DD)

  • YEAR
    • %Y = tahun empat digit, contoh: 2022
    • %y = tahun dua digit, contoh: 22
  • MONTH
    • %B = nama bulan, contoh: January
    • %b = nama bulan singkatan, contoh: Jan
    • %m = bulan dua digit, contoh: 01
  • DAY
    • %d = tanggal, contoh: 01 s.d. 31
  1. Kolom trending_date

Before:

# Cek struktur kolom trending_date
str(vids$trending_date)
#>  chr [1:13400] "17.14.11" "17.14.11" "17.14.11" "17.14.11" "17.14.11" ...

After:

# Ubah tipe data dengan as.Date(), lihat 6 data pertama 

 vids$trending_date <- as.Date(vids$trending_date, format="%y.%d.%m")
head(vids$trending_date)
#> [1] "2017-11-14" "2017-11-14" "2017-11-14" "2017-11-14" "2017-11-14"
#> [6] "2017-11-14"
  1. Kolom publish_time

Before:

# Inspeksi kolom publish_time
str(vids$publish_time)
#>  chr [1:13400] "2017-11-13T17:13:01.000Z" "2017-11-13T07:30:00.000Z" ...

After:

# Ubah tipe data dengan as.Date()
head(as.Date(vids$publish_time))
#> [1] "2017-11-13" "2017-11-13" "2017-11-12" "2017-11-13" "2017-11-12"
#> [6] "2017-11-13"
# Cek tipe data
class(as.Date(vids$publish_time))
#> [1] "Date"

📌 Important Points as.Date()

  • Format tanggal/date yang bisa langsung diubah dengan menggunakn as.Date() adalah Year-Month-Day
  • Penggunaan as.Date() menghilangkan format waktu
  • Jika format date/tanggal berbeda dengan default fungsi as.Date(), kita bisa menambahkan parameter format =.

Bagaimana jika kita perlu mempertahankan format waktu? 🤔

Menggunakan library lubridate

Penggunaan lubridate secara lengkap dapat dilihat di cheatsheet

#install.packages("lubridate")
library(lubridate)
  1. Kolom trending_date
# Cek tipe data
str(vids$trending_date)
#>  Date[1:13400], format: "2017-11-14" "2017-11-14" "2017-11-14" "2017-11-14" "2017-11-14" ...
# Format date dari kolom trending_date = Year-Day-Month
class(vids$trending_date)
#> [1] "Date"
  1. Kolom publish_time

Before:

# Cek tipe data
str(vids$publish_time)
#>  chr [1:13400] "2017-11-13T17:13:01.000Z" "2017-11-13T07:30:00.000Z" ...

After:

# Tambahkan timezone
vids$publish_time <- ymd_hms(vids$publish_time, tz="America/New_York") #data kita data dari new york
head(vids$publish_time)
#> [1] "2017-11-13 12:13:01 EST" "2017-11-13 02:30:00 EST"
#> [3] "2017-11-12 14:05:24 EST" "2017-11-13 06:00:04 EST"
#> [5] "2017-11-12 13:01:41 EST" "2017-11-13 14:07:23 EST"

Note: secara default, waktu akan diformat menjadi UTC, untuk menyematkan waktu daerah tertentu, gunakan parameter tz (timezome).

Nantinya kita akan menganalisis video YouTube yang sedang tren di AS, oleh karena itu lebih sesuai jika menggunakan zona waktu seperti New York.

Penulisan parameter timezone dapat dilihat pada list time zone

# Cek data setelah konversi
anyNA(vids$publish_time)
#> [1] FALSE

Feature Engineering

Membuat kolom (feature) baru atau memodifikasi kolom berdasarkan data yang ada

Membuat kolom-kolom baru yang berisi rasio

Buat kolom:

  • like_ratio: berisi likes / views
  • dislike_ratio: berisi dislikes / views
  • comment_ratio: berisi comment_count / views
# likes_view berisi likes / views
vids$like_ratio <-vids$likes / vids$views

# dislikes_view berisi dislikes / views
vids$dislike_ratio <-  vids$dislikes / vids$views

# comments_view berisi comment_count / views
vids$comment_ratio <-  vids$comment_count / vids$views
head(vids)

Membuat kolom-kolom baru dari data publish_time

  1. Buat kolom publish_date yang isinya hanya tanggal (YYYY-MM-DD) dari kolom publish_time
str(vids$publish_time)
#>  POSIXct[1:13400], format: "2017-11-13 12:13:01" "2017-11-13 02:30:00" "2017-11-12 14:05:24" ...
vids$publish_date <-  date(vids$publish_time)
head(vids$publish_date)
#> [1] "2017-11-13" "2017-11-13" "2017-11-12" "2017-11-13" "2017-11-12"
#> [6] "2017-11-13"
  1. Buat kolom baru berisi hari publish video dan jam publish video untuk vids. Beri nama publish_day dan publish_hour dari kolom publish_time
  • publish_day: nama hari publikasi video
vids$publish_day <-  wday(vids$publish_time, label=T, abbr=F)
head(vids$publish_day)
#> [1] Monday Monday Sunday Monday Sunday Monday
#> 7 Levels: Sunday < Monday < Tuesday < Wednesday < Thursday < ... < Saturday
  • publish_hour: jam publikasi video
vids$publish_hour <-  hour(vids$publish_time)
head(vids$publish_hour)
#> [1] 12  2 14  6 13 14
head(vids)

Mengambil judul video yang unik

Dalam data vids terdapat video yang muncul beberapa kali karena trending lebih dari 1 hari.

# Mengecek perbedaan total jumlah video dengan judul video yang unik
length(vids$title)
#> [1] 13400
length(unique(vids$title))
#> [1] 2986

Untuk analisis lanjutan, kita hanya ingin mengetahui kapan suatu video trending pertama kali. Untuk itu kita dapat menggunakan unique() dan match().

# Menggunakan match() dan unique()
vids_unik <- vids[match(unique(vids$title),vids$title),]
nrow(vids_unik)
#> [1] 2986
colnames(vids_unik)
#>  [1] "trending_date"          "title"                  "channel_title"         
#>  [4] "category_id"            "publish_time"           "views"                 
#>  [7] "likes"                  "dislikes"               "comment_count"         
#> [10] "comments_disabled"      "ratings_disabled"       "video_error_or_removed"
#> [13] "like_ratio"             "dislike_ratio"          "comment_ratio"         
#> [16] "publish_date"           "publish_day"            "publish_hour"

Visualization

Scatter Plot

Business Question: Bagaimana hubungan antara jumlah views dan likes pada video yang trending? Apakah video dengan lebih banyak views cenderung mendapatkan lebih banyak likes?

library(ggplot2)

# Membuat scatter plot
ggplot(data = vids_unik, aes(x = views, y = likes)) +
  geom_point(color = '#003049', alpha = 0.5) +  # Menggunakan titik biru dengan transparansi 50%
  labs(
    title = "Hubungan antara Views dan Likes pada Video Trending",
    x = "Views",
    y = "Likes"
  ) +
  theme_minimal() +  # Menggunakan tema minimalis untuk tampilan yang bersih
  theme(
    plot.title = element_text(hjust = 0.5)  # Memusatkan judul plot
  )

Penjelasan Code

  • ggplot(data = vids_unik, aes(x = views, y = likes)): Bagian ini menginisialisasi plot dengan menggunakan dataset vids_unik dan mengatur variabel views sebagai sumbu x dan likes sebagai sumbu y dengan fungsi aes (aesthetic mappings).

  • geom_point(color = ‘#003049’, alpha = 0.5): Fungsi ini menambahkan titik-titik pada scatter plot. Parameter color = ‘#003049’ menetapkan warna titik menjadi biru tua, dan alpha = 0.5 menetapkan transparansi titik menjadi 50%.

  • labs(): Fungsi ini digunakan untuk menambahkan elemen teks pada plot, seperti judul plot (title), label sumbu x (x), dan label sumbu y (y). Judul plot diatur menjadi “Hubungan antara Views dan Likes pada Video Trending”, label sumbu x diatur menjadi “Views”, dan label sumbu y diatur menjadi “Likes”.

  • theme_minimal(): Fungsi ini menerapkan tema minimalis pada plot, yang menghasilkan tampilan yang bersih dan sederhana dengan sedikit elemen visual.

  • theme(): Fungsi ini digunakan untuk mengatur elemen tema secara spesifik. Dalam hal ini, plot.title = element_text(hjust = 0.5) mengatur agar judul plot berada di tengah dengan menggunakan hjust = 0.5 (horizontal justification).

Interpretasi

  • Terdapat korelasi positif antara jumlah views dan likes. Artinya, video yang memiliki lebih banyak views cenderung juga memiliki lebih banyak likes. Ini terlihat dari pola titik-titik yang naik dari kiri bawah (sedikit views dan sedikit likes) ke kanan atas (banyak views dan banyak likes).

Heatmap

Business Question: Bagaimana distribusi korelasi antar variabel numerik dalam dataset video trending? Apakah terdapat hubungan kuat antara variabel-variabel tersebut?

Kita akan membuat heatmap menggunakan variabel numerik dalam dataset vids_unik. Variabel numerik yang dapat digunakan adalah: views, likes, dislikes, comment_count, like_ratio, dislike_ratio, comment_ratio, publish_hour.

library(reshape2)

# Memilih hanya kolom numerik dari dataset
numerik_cols <- vids_unik[, c("views", "likes", "dislikes", "comment_count", 
                              "like_ratio", "dislike_ratio", "comment_ratio", "publish_hour")]

# Membuat matriks korelasi
cor_matrix <- cor(numerik_cols, use = "complete.obs")

# Melelehkan matriks korelasi menjadi format panjang (long format)
melted_cor_matrix <- melt(cor_matrix)

# Membuat heatmap dengan ggplot2
ggplot(data = melted_cor_matrix, aes(x = Var1, y = Var2, fill = value)) +
  geom_tile(color = "white") +
  scale_fill_gradient2(low = "#003049", high = "red", mid = "white",
                       midpoint = 0, limit = c(-1, 1), space = "Lab",
                       name = "Correlation") +
  labs(
    title = "Heatmap Korelasi Antar Variabel Numerik",
    x = "Variabel",
    y = "Variabel"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1),
    plot.title = element_text(hjust = 0.5)
  )

Penjelasan Code

  • Fungsi cor() digunakan untuk menghitung matriks korelasi dari kolom-kolom numerik yang dipilih. Parameter use = “complete.obs” memastikan bahwa perhitungan korelasi hanya menggunakan pengamatan lengkap (tanpa missing values).

  • Fungsi melt() dari pustaka reshape2 digunakan untuk mengubah matriks korelasi dari format lebar (wide format) ke format panjang (long format). Format panjang diperlukan agar ggplot2 dapat menggunakannya untuk membuat heatmap.

  • ggplot(data = melted_cor_matrix, aes(x = Var1, y = Var2, fill = value)): Inisialisasi plot dengan dataset melted_cor_matrix. Var1 dan Var2 adalah variabel pada sumbu x dan y, sedangkan value adalah nilai korelasi yang digunakan untuk mengisi warna.

  • geom_tile(color = “white”): Menambahkan kotak (tile) ke plot untuk setiap pasangan variabel dengan warna garis luar putih.

  • scale_fill_gradient2(…): Mengatur skala warna untuk heatmap. low = “blue” menetapkan warna biru untuk nilai korelasi rendah, high = “red” untuk nilai korelasi tinggi, dan mid = “white” untuk nilai korelasi tengah (0). midpoint = 0 menetapkan titik tengah pada skala warna di 0, dan limit = c(-1, 1) menetapkan batasan rentang korelasi.

  • theme(…): Menyesuaikan elemen tema. axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1) memutar teks sumbu x sebesar 45 derajat agar lebih mudah dibaca. plot.title = element_text(hjust = 0.5) memusatkan judul plot.

Interpretasi

  • Terdapat korelasi yang sangat kuat antara views dengan likes, dislikes, dan comment count. Ini terlihat dari warna merah pekat di persilangan antar variabel tersebut, yang menunjukkan bahwa semakin banyak views yang dimiliki sebuah video, semakin banyak likes, dislikes, dan komentar yang diterima.

  • Korelasi antara likes dan comment count juga cukup kuat, menunjukkan bahwa video dengan banyak likes cenderung memiliki banyak komentar.

  • Publish hour (jam publikasi) tidak menunjukkan korelasi yang kuat dengan variabel lainnya, menunjukkan bahwa waktu publikasi tidak terlalu mempengaruhi jumlah views, likes, dislikes, atau komentar yang diterima.

Line Plot (Time Series)

Business Question: Bagaimana tren rata-rata jumlah penonton (views) untuk video yang dipublikasikan pada waktu yang berbeda? Apakah ada jam-jam publish tertentu yang cenderung menghasilkan lebih banyak penonton?

head(vids_unik)
library(dplyr)
# Menghitung rata-rata views di setiap jam publish
avg_views_by_date <- vids_unik %>%
  group_by(publish_hour) %>%
  summarise(avg_views = mean(views, na.rm = TRUE))

# Membuat line plot time series dengan ggplot2
ggplot(data = avg_views_by_date, aes(x = publish_hour, y = avg_views)) +
  geom_line(color = '#003049') +
  labs(
    title = "Tren Rata-rata Jumlah Penonton (Views) di Setiap Jam Publish",
    x = "Jam Publish",
    y = "Rata-rata Views"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5)
  )

Penjelasan Code

  • Inisialisasi plot dilakukan dengan ggplot(), menggunakan dataset avg_views_by_date. Variabel publish_hour digunakan sebagai sumbu x dan avg_views sebagai sumbu y dalam fungsi aes().

  • geom_line(color = ‘#003049’) menambahkan garis pada plot dengan warna biru tua.

  • labs() digunakan untuk menambahkan judul dan label sumbu. Judul plot diatur menjadi “Tren Rata-rata Jumlah Penonton (Views) di Setiap Jam Publish”, sedangkan label sumbu x dan y diatur menjadi “Jam Publish” dan “Rata-rata Views” secara berturut-turut.

  • theme(plot.title = element_text(hjust = 0.5)) digunakan untuk memusatkan judul plot secara horizontal.

Interpretasi

  • Secara keseluruhan, dapat disimpulkan bahwa video yang dipublikasikan pada jam-jam tertentu, khususnya sekitar jam 4-5 pagi, cenderung mendapatkan lebih banyak penonton. Di luar waktu-waktu tersebut, rata-rata jumlah views cenderung stabil dengan beberapa fluktuasi kecil. Jam publish bisa menjadi faktor yang penting untuk dipertimbangkan bagi konten kreator yang ingin memaksimalkan jumlah penonton.

Visualisasi Data Spasial

Untuk melakukan visualisasi spasial, kita akan menggunakan Data Demografi Kabupaten Bogor. Data bersumber dari Badan Pusat Statistik dengan jumlah kecamatan sebanyak 40 kecamatan. Data ini merupakan data luaran Kementerian Dalam Negeri (Kemendagri 2020).

# Membaca data dengan delimiter titik koma
data <- read.csv("https://raw.githubusercontent.com/farhanabdillahh/Regresi-Spasial/main/Data/Data_KabBogor.csv", header = TRUE, sep = ";")

# Menampilkan struktur data
head(data)

Data Spasial Data spasial merupakan data yang merepresentasikan gambaran kejadian di permukaan bumi yang disajikan dalam bentuk peta, grafik dan gambar berformat digital. Data spasial tidak hanya terdiri dari baris dan kolom seperti data tabular pada umumnya, tetapi juga mencakup informasi geometris objek seperti titik (koordinat), garis, dan poligon atau area. Data spasial yang digunakan dalam praktik ini adalah Shapefile yang diperoleh dari website data.humdata.org (HDX 2020)

library(sf)

Membaca data spasial dapat dilakukan dengan menggunakan fungsi st_read() dari paket sf.

mapInd <- st_read("data_input/shp/idn_admbnda_adm3_bps_20200401.shp", 
                        quiet = TRUE)
glimpse(mapInd)
#> Rows: 7,069
#> Columns: 17
#> $ Shape_Leng <dbl> 0.2798656, 0.7514001, 0.6900061, 0.6483629, 0.2437073, 1.35…
#> $ Shape_Area <dbl> 0.003107633, 0.016925540, 0.024636382, 0.010761277, 0.00116…
#> $ ADM3_EN    <chr> "2 X 11 Enam Lingkung", "2 X 11 Kayu Tanam", "Abab", "Abang…
#> $ ADM3_PCODE <chr> "ID1306050", "ID1306052", "ID1612030", "ID5107050", "ID7471…
#> $ ADM3_REF   <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ ADM3ALT1EN <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ ADM3ALT2EN <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ ADM2_EN    <chr> "Padang Pariaman", "Padang Pariaman", "Penukal Abab Lematan…
#> $ ADM2_PCODE <chr> "ID1306", "ID1306", "ID1612", "ID5107", "ID7471", "ID9432",…
#> $ ADM1_EN    <chr> "Sumatera Barat", "Sumatera Barat", "Sumatera Selatan", "Ba…
#> $ ADM1_PCODE <chr> "ID13", "ID13", "ID16", "ID51", "ID74", "ID94", "ID94", "ID…
#> $ ADM0_EN    <chr> "Indonesia", "Indonesia", "Indonesia", "Indonesia", "Indone…
#> $ ADM0_PCODE <chr> "ID", "ID", "ID", "ID", "ID", "ID", "ID", "ID", "ID", "ID",…
#> $ date       <date> 2019-12-20, 2019-12-20, 2019-12-20, 2019-12-20, 2019-12-20…
#> $ validOn    <date> 2020-04-01, 2020-04-01, 2020-04-01, 2020-04-01, 2020-04-01…
#> $ validTo    <date> -001-11-30, -001-11-30, -001-11-30, -001-11-30, -001-11-30…
#> $ geometry   <MULTIPOLYGON [°]> MULTIPOLYGON (((100.2811 -0..., MULTIPOLYGON (…

Selanjutnya akan dilakukan merged data peubah Kode BPS dari data Bogor, dan peubah ADM3_PCODE dari mapInd.

mapBogor<- mapInd %>%
  inner_join(data, by = c("ADM3_PCODE" = "Kode.BPS"))
mapBogor

Jumlah Penduduk yang Tersebar di Kabupaten Bogor

Untuk menyajikan dalam peta choropleth, beberapa paket R dapat digunakan, salah satunya paket ggplot2 dengan fungsi geom_sf(). Berikut merupakan visualisasi yang merepresentasikan sebaran jumlah penduduk yang tersebar di kabupaten Bogor:

Jumlah_Penduduk <- ggplot() +  
  geom_sf(data=mapBogor, aes(fill=`Jumlah.Penduduk`))
Jumlah_Penduduk

Interpretasi

  • Wilayah-wilayah di bagian barat, selatan, dan sebagian besar wilayah di timur memiliki jumlah penduduk yang lebih rendah, berkisar antara 100.000 hingga 200.000 penduduk.