Shiny merupakan packages dari RStudio, yang menyediakan framework aplikasi web untuk membuat aplikasi web interaktif (visualisasi) yang disebut “Shiny apps”. Kemudahan bekerja dengan Shiny telah mempopulerkannya di antara pengguna R. Aplikasi web ini menampilkan objek R dengan cantik (seperti plot, tabel, dll.) dan juga dapat di-deploy untuk memungkinkan diakses oleh siapa saja.
Shiny menyediakan widget yang memungkinkan untuk membangun aplikasi yang elegan dengan sedikit usaha.
Struktur aplikasi shiny dasar:
Langkah mempersiapkan projek shiny dashboard dengan template Shiny Web App:
Pilih Menu File > New File > Shiny Web App
Isi Application Name sesuai dengan nama projek yang diinginkan
Pilih Application Type nya adalah Multipe File (ui.R/server.R)
Pilih directory folder projek di bagian Browse (create within directory)
Membuat Rproject baru dalam directory nomor 4 dengan cara:
Copy data input ke dalam folder nomor 4
Membuat global.R
dengan cara Menu
File -> R Script -> Save (ctrl +
s) dengan File Name = global.R
Dalam Shiny Dashboard, layout dasar dibangun dengan menggunakan 3 komponen utama, yaitu:
Berikut adalah kode dasar yang digunakan untuk membuat layout dengan tiga komponen tersebut:
dashboardPage(
# ------ Bagian Header ------
dashboardHeader(),
# ----- Bagian Sidebar ------
dashboardSidebar(),
# ----- Bagian Main / Body ------
dashboardBody()
)
Pada langkah ini, kita akan menambahkan judul pada dashboard
menggunakan fungsi dashboardHeader()
.
Judul ini akan muncul di bagian atas dashboard, yang membantu pengguna mengetahui fokus atau tujuan dari aplikasi yang sedang mereka gunakan.
Berikut adalah contohnya:
dashboardPage(
# ------ Bagian Header ------
dashboardHeader(
title = "Youtube Analysis" # Menambahkan judul pada header
),
# ----- Bagian Sidebar ------
dashboardSidebar(),
# ----- Bagian Main / Body ------
dashboardBody()
)
File global merupakan tempat untuk mengatur semua pengaturan yang akan digunakan secara global di seluruh aplikasi Shiny. File ini biasanya berisi import library, membaca data, dan proses pembersihan (data cleansing) sebelum data digunakan dalam aplikasi. Dengan begitu, kode yang mengelola data tidak perlu diulang di setiap bagian aplikasi.
Pada bagian ini, kita akan melakukan beberapa langkah penting, termasuk mengimpor pustaka (library), membaca data, dan melakukan data cleansing.
library(shiny)
library(shinydashboard)
# import library
library(dplyr)
library(ggplot2)
library(scales)
library(glue)
library(plotly)
library(lubridate)
options(scipen = 100)
# read data
vids <- read.csv("data_input/youtubetrends_2023.csv", stringsAsFactors = TRUE, encoding = "latin1")
# cleansing data
vids_clean <- vids %>%
# deselect kolom yang tidak dibutuhkan
select(-c(comments_disabled, ratings_disabled, video_error_or_removed)) %>%
# manipulasi kolom
mutate(
# mengubah tipe data
trending_date = ymd(trending_date),
publish_time = ymd_hms(publish_time),
title = as.character(title),
channel_title = as.character(channel_title),
# menambah kolom baru
likesp = likes/views,
dislikep = dislikes/views,
commentp = comment_count/views
)
fluidRow
Pada bagian ini, kita akan menyusun layout untuk halaman pertama. Layout tersebut akan terdiri dari dua baris dengan pengaturan sebagai berikut:
infoBox()
. Kotak ini berisi informasi
penting seperti jumlah total video dan jumlah channel yang
trending.box()
. Kotak ini dapat berisi
visualisasi atau konten lain sesuai kebutuhan.Pengaturan lebar kotak diatur menggunakan parameter
width
, dengan nilai berkisar antara 1 hingga 12, yang
merepresentasikan lebar dari satu baris penuh. Nilai ini memungkinkan
kita mengatur ukuran setiap kotak secara fleksibel.
Berikut adalah contoh implementasinya:
# ----- Page 1
tabItem(
tabName = "page1",
# ----- Page 1 Row 1 -----
fluidRow(
# Kotak pertama menampilkan total video
infoBox(
width = 6, # Lebar kotak 6 dari total 12 kolom
title = "Total Video Count"
),
# Kotak kedua menampilkan total channel yang trending
infoBox(
width = 6, # Lebar kotak 6 dari total 12 kolom
title = "Total Trending Channel"
)
),
# ----- Page 1 Row 2 -----
fluidRow(
# Kotak untuk konten tambahan (misalnya grafik atau tabel)
box(
width = 12 # Lebar kotak memenuhi seluruh baris
)
)
)
infoBox
Pada tahap ini, kita akan menambahkan nilai (value), ikon, dan warna
pada elemen infoBox
untuk memperkaya tampilan dan
memberikan informasi yang lebih jelas kepada pengguna. Setiap
infoBox
akan berisi:
Berikut adalah implementasinya:
# ----- Page 1 Row 1 -----
fluidRow(
# InfoBox untuk menampilkan jumlah total video
infoBox(
width = 6, # Lebar 6 kolom
title = "Total Video Count", # Judul kotak
value = comma(nrow(vids_clean)), # Menampilkan jumlah total video, diformat dengan comma
icon = icon("youtube"), # Menampilkan ikon YouTube
color = "red" # Warna kotak merah
),
# InfoBox untuk menampilkan jumlah channel yang trending
infoBox(
width = 6, # Lebar 6 kolom
title = "Total Trending Channel", # Judul kotak
value = comma(length(unique(vids_clean$channel_title))), # Menampilkan jumlah channel yang unik
icon = icon("headset"), # Menampilkan ikon headset
color = "black" # Warna kotak hitam
)
)
box
untuk
plotlyOutput
Pada bagian ini, kita akan menambahkan elemen visualisasi interaktif
menggunakan plotlyOutput
ke dalam box
.
Visualisasi ini nantinya akan menampilkan grafik yang dapat berinteraksi
dengan pengguna. Fungsi plotlyOutput
digunakan untuk
merender grafik yang dihasilkan dari Plotly
, yang merupakan
library visualisasi data interaktif.
Berikut adalah implementasinya:
# ----- Page 1 Row 2 -----
fluidRow(
box(
width = 12, # Lebar box penuh (12 kolom)
# Menampilkan output plotly dengan ID "plot1_bar"
plotlyOutput(outputId = "plot1_bar")
)
)
Penjelasan:
Plotly
. ID "plot1_bar"
digunakan untuk merujuk
ke plot yang akan dirender pada bagian server aplikasi.server.R
Setelah kita menyiapkan box
untuk menampung plot di
ui.R
dan mengatur outputId
menjadi
"plot1_bar"
, kita perlu melengkapi bagian
server.R
untuk menghasilkan plot yang diinginkan.
Dalam bagian ini, kita akan melakukan penugasan pada ID yang telah
kita buat di UI menggunakan sintaks output$nama_id <-
.
Mengingat bahwa kita telah menggunakan plotlyOutput
di UI,
kita perlu menggunakan fungsi renderPlotly({})
di
server.
Berikut adalah langkah-langkah yang perlu diikuti:
category_id
dan menghitung jumlah video untuk
setiap kategori.ggplot2
untuk
membuat plot batang, dan mengonversinya menjadi objek interaktif
menggunakan ggplotly()
dari Plotly
.Berikut adalah implementasinya:
shinyServer(function(input, output) {
# ---- Kode untuk Barplot (plot1) ----
output$plot1_bar <- renderPlotly({
# Data Wrangling
vids_count <- vids_clean %>%
group_by(category_id) %>%
summarise(count = n()) %>%
ungroup() %>%
arrange(-count)
vids_count <- vids_count %>%
mutate(
label = glue(
"Category: {category_id}
Video count: {count}"
)
)
# Visualization
plot1 <- ggplot(data = vids_count, aes(x = count,
y = reorder(category_id, count),
text = label)) + # reorder(A, berdasarkan B)
geom_col(aes(fill = count)) +
scale_fill_gradient(low="red", high="black") +
labs(title = "Trending Categories of YouTube US 2023",
x = "Video Count",
y = NULL) +
scale_x_continuous(labels = comma) +
theme_minimal() +
theme(legend.position = "none")
ggplotly(plot1, tooltip = "text")
})
})
fluidRow
Pada halaman kedua, kita akan memulai dengan menyusun layout
menggunakan fluidRow
dan menambahkan box
sesuai kebutuhan. Hal ini mirip dengan pengaturan yang telah kita
lakukan di halaman pertama.
Kita akan membuat dua baris di halaman ini:
box
yang memenuhi
lebar penuh (12).box
yang
masing-masing mengambil setengah lebar (6).Berikut adalah implementasi kode untuk menyusun layout di halaman kedua:
# ----- Page 2
tabItem(
tabName = "page2",
# ------- Page 2 Row 1
fluidRow(
box(
width = 12
)
),
# ------- Page 2 Row 2
fluidRow(
box(
width = 6
),
box(
width = 6
)
)
),
selectInput
Pada bagian ini, kita akan mengisi box di halaman kedua, baris pertama, dengan sebuah input. Input ini akan membantu pengguna untuk memilih kategori video yang diinginkan dari dataset yang tersedia. Ada berbagai macam pilihan input yang dapat dipilih sesuai dengan data atau kebutuhan spesifik aplikasi kita.
Untuk kasus ini, kita akan menyediakan sebuah input yang memungkinkan
pengguna untuk memilih kategori video, sehingga tipe input yang cocok
adalah selectInput
. Dengan selectInput
,
pengguna dapat memilih satu kategori dari daftar pilihan yang telah
disediakan.
selectInput(...)
:
inputId = "input_category"
: ID unik
untuk input yang akan digunakan dalam logika server.label = "Pilih Kategori Video"
: Label
yang akan ditampilkan di samping input.choices = unique(vids_clean$category_id)
:
Daftar pilihan diisi dengan kategori video yang tersedia dari dataset
vids_clean
.selected = "Gaming"
: Menetapkan nilai
default yang akan ditampilkan saat pertama kali pengguna membuka
dashboard.Berikut adalah implementasi kode untuk menambahkan
selectInput
ke dalam layout:
# ------- Page 2 Row 1
fluidRow(
box(
width = 12,
selectInput(
inputId = "input_category",
label = "Choose video category", # Label untuk input
choices = unique(vids_clean$category_id), # Daftar pilihan diambil dari kategori yang ada
selected = "Gaming" # Pilihan default
)
)
),
plotlyOutput
pada Baris
KeduaPada bagian ini, kita akan menambahkan elemen untuk menampilkan plot
di halaman kedua, baris kedua. Sama seperti yang telah kita lakukan
sebelumnya, kita akan menyediakan ID untuk plotlyOutput
,
yang selanjutnya perlu disesuaikan pada bagian server agar plot dapat
ditampilkan dengan benar.
Kita akan membuat dua box di baris ini, satu untuk plot lollipop dan satu lagi untuk plot line Berikut adalah implementasi kodenya:
server.R
Sama seperti sebelumnya kita akan melakukan assignment pada
masing-masing id yang telah kita buat pada bagian ui.R
# ---- Kode untuk Lolipop plot (plot2) ----
output$plot2_lolipop <- renderPlotly({
# Data wrangling
vids_10 <- vids_clean %>%
filter(category_id=="Gaming") %>%
group_by(channel_title) %>%
summarise(mean_viewers = mean(views)) %>%
ungroup() %>%
arrange(-mean_viewers) %>%
head(10)
vids_10 <- vids_10 %>%
mutate(label = glue(
"Channel : {channel_title}
Average Views: {comma(mean_viewers)}"
)
)
# Visualization
plot2 <- ggplot(vids_10, aes(x = reorder(channel_title, mean_viewers),
y = mean_viewers,
text = label)) +
geom_segment(aes(xend=reorder(channel_title, mean_viewers), y=0,yend=mean_viewers), color="red") +
geom_point(color="black", size=3) +
coord_flip() +
scale_y_continuous(labels = comma) +
labs(title = "Top 10 Channel on Gaming",
x = NULL,
y = "Average View") +
theme_minimal()
ggplotly(plot2, tooltip = "text")
})
# ---- Kode untuk Lineplot (plot3) ----
output$plot3_line <- renderPlotly({
# Data wrangling
vids_trend <- vids_clean %>%
filter(category_id == "Gaming") %>%
group_by(publish_hour) %>%
summarise(avg_views = mean(views)) %>%
ungroup() %>%
mutate(
label2 = glue(
"Publish Hour: {publish_hour}
Average views: {comma(round(avg_views, 2))}"
)
)
# Visualization
plot3 <- ggplot(vids_trend, aes(x=publish_hour, y= avg_views))+
geom_line(col="red") +
geom_point(aes(text=label2), col="black") +
scale_y_continuous(labels = comma , breaks = seq(0, 8000000, 1000000)) +
scale_x_continuous(breaks = seq(0,23,1)) +
labs(
title = "Viewers Activity of Gaming Videos",
x = "Publish Hours",
y = "Average Views"
) +
theme_minimal()
ggplotly(plot3, tooltip = "text")
})
Setelah menambahkan input dan plot output, langkah selanjutnya adalah menghubungkan kedua elemen ini sehingga ketika pengguna memilih kategori video dari dropdown, visualisasi akan diperbarui secara otomatis.
Dalam konteks visualisasi ini, nilai input yang dipilih akan
berfungsi sebagai filter untuk category_id
, sehingga kita
dapat memproses data sesuai dengan kategori yang dipilih sebelum
melakukan visualisasi.
Oleh sebab, itu kita akan mengganti kode "Gaming"
pada
filter(category_id == "Gaming")
dengan id inputan yang telah kita buat.
Untuk mengakses id menjad nilai dinamis sesuai inputan yang dipilih
user, kita dapat menggunakan syntaks input$id
input$input_category
Berikut implementasinya
# ---- Kode untuk Lolipop plot (plot2) ----
output$plot2_lolipop <- renderPlotly({
# Data wrangling
vids_10 <- vids_clean %>%
filter(category_id==input$input_category) %>%
group_by(channel_title) %>%
summarise(mean_viewers = mean(views)) %>%
ungroup() %>%
arrange(-mean_viewers) %>%
head(10)
vids_10 <- vids_10 %>%
mutate(label = glue(
"Channel : {channel_title}
Average Views: {comma(mean_viewers)}"
)
)
# Visualization
plot2 <- ggplot(vids_10, aes(x = reorder(channel_title, mean_viewers),
y = mean_viewers,
text = label)) +
geom_segment(aes(xend=reorder(channel_title, mean_viewers), y=0,yend=mean_viewers), color="red") +
geom_point(color="black", size=3) +
coord_flip() +
scale_y_continuous(labels = comma) +
labs(title = glue("Top 10 Channel on {input$input_category}"),
x = NULL,
y = "Average View") +
theme_minimal()
ggplotly(plot2, tooltip = "text")
})
# ---- Kode untuk Lineplot (plot3) ----
output$plot3_line <- renderPlotly({
# Data wrangling
vids_trend <- vids_clean %>%
filter(category_id == input$input_category) %>%
group_by(publish_hour) %>%
summarise(avg_views = mean(views)) %>%
ungroup() %>%
mutate(
label2 = glue(
"Publish Hour: {publish_hour}
Average views: {comma(round(avg_views, 2))}"
)
)
# Visualization
plot3 <- ggplot(vids_trend, aes(x=publish_hour, y= avg_views))+
geom_line(col="red") +
geom_point(aes(text=label2), col="black") +
scale_y_continuous(labels = comma , breaks = seq(0, 8000000, 1000000)) +
scale_x_continuous(breaks = seq(0,23,1)) +
labs(
title = glue("Viewers Activity of {input$input_category} Videos"),
x = "Publish Hours",
y = "Average Views"
) +
theme_minimal()
ggplotly(plot3, tooltip = "text")
})
Untuk menampilkan data tabel dalam aplikasi Shiny, kita akan
menggunakan library DT
yang memungkinkan kita untuk membuat
tabel interaktif. Berikut adalah langkah-langkah untuk menyusun layout
pada halaman ketiga aplikasi kita.
server.R
Setelah layout diatur, langkah selanjutnya adalah menyediakan output
data tabel di bagian server.R
. Kita akan menggunakan fungsi
renderDT
dari library DT
untuk merender
dataset yang bersih (vids_clean
) ke dalam tabel
interaktif.
# ---- Kode untuk menampilkan dataset table
output$dataset <- DT::renderDT(
vids_clean,
options = list(scrollX = TRUE, # Memungkinkan scroll horizontal
scrollY = TRUE) # Memungkinkan scroll vertikal
)
Untuk meningkatkan tampilan dan nuansa aplikasi Shiny Dashboard kita,
kita dapat mengatur tema dan gaya dengan menggunakan berbagai opsi yang
disediakan oleh paket shinydashboard
. Anda dapat menemukan
informasi lebih lanjut dan dokumentasi lengkap tentang penampilan di dokumentasi
resmi shinydashboard.
Berikut adalah beberapa langkah yang dapat Anda ikuti untuk mengatur tema pada Shiny Dashboard:
Anda bisa mengubah tema dasar dashboard dengan menggunakan parameter
dashboardBody()
, seperti berikut:
dashboardBody(
# Mengatur tema dengan menambahkan CSS
tags$head(
tags$style(HTML('
/* Mengubah warna latar belakang dan warna teks */
.skin-blue .main-header .logo {
background-color: #3c8dbc;
color: #fff;
}
.skin-blue .main-header .navbar {
background-color: #3c8dbc;
}
.skin-blue .main-header .navbar .sidebar-toggle {
background-color: #3c8dbc;
}
.skin-blue .main-sidebar {
background-color: #f4f4f4;
}
.skin-blue .main-footer {
background-color: #3c8dbc;
color: #fff;
}
'))
),
# Konten lainnya...
)
Anda dapat menambahkan ikon pada menu dengan menggunakan paket
fontAwesome
:
library(shiny)
library(shinydashboard)
dashboardPage(
dashboardHeader(title = "YouTube Dashboard"),
dashboardSidebar(
sidebarMenu(
menuItem("Page 1", tabName = "page1", icon = icon("dashboard")),
menuItem("Page 2", tabName = "page2", icon = icon("video")),
menuItem("Page 3", tabName = "page3", icon = icon("table"))
)
),
dashboardBody(
# Konten body...
)
)
Anda juga dapat mengubah warna teks dan latar belakang di bagian body:
Anda juga dapat mengatur komponen lain seperti ukuran font, batas,
padding, dan margin untuk mencapai tampilan yang diinginkan dengan
menambahkan lebih banyak CSS di bagian tags$head()
.