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
)fluidRowPada 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
)
)
)infoBoxPada 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
plotlyOutputPada 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.RSetelah 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")
})
})fluidRowPada 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
)
)
),selectInputPada 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.RSama 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.RSetelah 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().