Ketika menyelesaikan atau sedang memainkan suatu game, ada rasa penasaran atau sekedar pertanyaan “Kirakira, ada tidak ya game seperti ini lagi?”. Alternatif yang kita cari ini bisa memberikan informasi untuk merasakan pengalaman bermain sesuai dengan preferensi kita. Mengacu pada artikel dari nationaltoday.com, tercatat saat ini ada lebih dari 5 juta games. Pastinya akan sangat mustahil jika kita mencoba atau menelusuri satu per satu 5 juta games tersebut.
Jika membandingkan antara jumlah game yang beredar saat ini dengan rata-rata waktu yang kita habiskan untuk bermain game, tentulah kita harus memilah game mana yang akan kita mainkan. Artikel pada forbes.com mengatakan rata-rata player menghabiskan 8.6 jam dalam seminggu untuk bermain video games.
“Based on data gathered from 800 gamers around the world, players spend 8.6 hours per week playing video games, roughly equating to 1.2 hours a day. Presuming this is consistent, that’s 2.5 weeks each year, and 2.8 years across the standard lifetime–around 4% of our time on Earth.”
Dari pertimbangan banyaknya jumlah game dengan rata-rata durasi yang kita habiskan untuk bermain, tentunya kita harus dapat memilah mana game yang akan kita mainkan berikutnya. Terkadang proses pemilihan ini sangatlah banyak faktor yang dipertimbangkan, mulai dari genre, fitur dalam game, rating games, review sesama player, atau bahkan developer game. Adanya sebuah sistem rekomendasi yang dapat memberikan alternatif pilihan tentunya akan sangat membantu kita untuk memilih game yang akan kita mainkan.
Pada project kali ini, kita akan mencoba membuat dashboard rekomendasi untuk games. Dashboard akan menerima input berupa preferensi dari player, dan memberikan output berupa sekelompok rekomendasi games yang sesuai dengan preferensi. Selain itu, dashboard juga akan memberikan informasi dari hasil Exploratory Data Analysis, misal games dengan rating positive terbanyak, atau games dengan user terbanyak.
Melalui project ini diharapkan dapat memberi dampak berikut:
Project kali ini akan menggunakan data dari platform games, yaitu Steam. Data yang akan digunakan berasal dari Kaggle. Pada dataset ini terdapat kolom berikut:
appid : id dari gamesname : nama gamesrelease_date : tanggal rilis gamesenglish : games tersedia dalam englishdeveloper : developer dari gamespublisher : publisher dari gamesplatforms : platform OS yang mendukung gamesrequired_age : batas usia memainkan gamescategories : kategori gamesgenres : genre dari gamessteamspy_tags : tags dari platform steam untuk gamesachievements : berapa banyak acheivements dari gamespositive_ratings : jumlah rating positive yang diperoleh gamesnegative_ratings : jumlah rating negative yang diperoleh gamesaverage_playtime : rata-rata waktu memainkan gamesmedian_playtime : median waktu memainkan gamesowners : rentang jumlah orang yang memiliki gamesprice : harga dari games.Untuk model machine learning yang akan digunakan adalah K-Medoids Clustering (PAM) dan K-Means Clustering.
Catatan: Pendekatan lain yang mungkin akan digunakan, yaitu collaborative filtering/content base filtering dengan package recommenderlab jika memungkinkan.
Data yang didapatkan masih berupa raw data, dan harus disiapkan sebelum dilanjutkan ke tahap analisis.
Berikut adalah library yang akan digunakan pada propsal project ini.
#data wrangling
library(tidyverse)
library(lubridate)
#EDA&visualisasi
library(plotly)
library(glue)Catatan: library yang dituliskan hanya untuk kebutuhan proposal, belum memasukan library untuk project nantinya.
Kita akan membaca file data dan memberi nama sebagai steam.
#read file
steam <- read.csv(file = "data/steam/steam.csv")
steamTerdapat 27.075 baris, dan 18 kolom. Penjelasan mengenai kolom tersebut dapat merujuk pada bagian Data Collection.
Terdapat kolom yang masih dalam tipe belum sesuai dan kita akan mengubah ke tipe yang lebih tepat.
str(steam)#> 'data.frame': 27075 obs. of 18 variables:
#> $ appid : int 10 20 30 40 50 60 70 80 130 220 ...
#> $ name : chr "Counter-Strike" "Team Fortress Classic" "Day of Defeat" "Deathmatch Classic" ...
#> $ release_date : chr "2000-11-01" "1999-04-01" "2003-05-01" "2001-06-01" ...
#> $ english : int 1 1 1 1 1 1 1 1 1 1 ...
#> $ developer : chr "Valve" "Valve" "Valve" "Valve" ...
#> $ publisher : chr "Valve" "Valve" "Valve" "Valve" ...
#> $ platforms : chr "windows;mac;linux" "windows;mac;linux" "windows;mac;linux" "windows;mac;linux" ...
#> $ required_age : int 0 0 0 0 0 0 0 0 0 0 ...
#> $ categories : chr "Multi-player;Online Multi-Player;Local Multi-Player;Valve Anti-Cheat enabled" "Multi-player;Online Multi-Player;Local Multi-Player;Valve Anti-Cheat enabled" "Multi-player;Valve Anti-Cheat enabled" "Multi-player;Online Multi-Player;Local Multi-Player;Valve Anti-Cheat enabled" ...
#> $ genres : chr "Action" "Action" "Action" "Action" ...
#> $ steamspy_tags : chr "Action;FPS;Multiplayer" "Action;FPS;Multiplayer" "FPS;World War II;Multiplayer" "Action;FPS;Multiplayer" ...
#> $ achievements : int 0 0 0 0 0 0 0 0 0 33 ...
#> $ positive_ratings: int 124534 3318 3416 1273 5250 2758 27755 12120 3822 67902 ...
#> $ negative_ratings: int 3339 633 398 267 288 684 1100 1439 420 2419 ...
#> $ average_playtime: int 17612 277 187 258 624 175 1300 427 361 691 ...
#> $ median_playtime : int 317 62 34 184 415 10 83 43 205 402 ...
#> $ owners : chr "10000000-20000000" "5000000-10000000" "5000000-10000000" "5000000-10000000" ...
#> $ price : num 7.19 3.99 3.99 3.99 3.99 3.99 7.19 7.19 3.99 7.19 ...
#change data types
steam_clean <- steam %>%
mutate_at(
vars(
english,
categories,
platforms,
genres,
steamspy_tags,
required_age,
owners
), as.factor
)
steam_clean$release_date <- ymd(steam_clean$release_date)
head(steam_clean)steam_clean %>%
str()#> 'data.frame': 27075 obs. of 18 variables:
#> $ appid : int 10 20 30 40 50 60 70 80 130 220 ...
#> $ name : chr "Counter-Strike" "Team Fortress Classic" "Day of Defeat" "Deathmatch Classic" ...
#> $ release_date : Date, format: "2000-11-01" "1999-04-01" ...
#> $ english : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
#> $ developer : chr "Valve" "Valve" "Valve" "Valve" ...
#> $ publisher : chr "Valve" "Valve" "Valve" "Valve" ...
#> $ platforms : Factor w/ 7 levels "linux","mac",..: 7 7 7 7 7 7 7 7 7 7 ...
#> $ required_age : Factor w/ 6 levels "0","3","7","12",..: 1 1 1 1 1 1 1 1 1 1 ...
#> $ categories : Factor w/ 3333 levels "Captions available",..: 330 330 498 330 2487 457 2292 2487 624 3062 ...
#> $ genres : Factor w/ 1552 levels "Accounting;Animation & Modeling;Audio Production;Design & Illustration;Education;Photo Editing;Software Trainin"| __truncated__,..: 3 3 3 3 3 3 3 3 3 3 ...
#> $ steamspy_tags : Factor w/ 6423 levels "1980s;Great Soundtrack;Retro",..: 225 225 2583 225 2554 225 2562 225 2554 2554 ...
#> $ achievements : int 0 0 0 0 0 0 0 0 0 33 ...
#> $ positive_ratings: int 124534 3318 3416 1273 5250 2758 27755 12120 3822 67902 ...
#> $ negative_ratings: int 3339 633 398 267 288 684 1100 1439 420 2419 ...
#> $ average_playtime: int 17612 277 187 258 624 175 1300 427 361 691 ...
#> $ median_playtime : int 317 62 34 184 415 10 83 43 205 402 ...
#> $ owners : Factor w/ 13 levels "0-20000","100000-200000",..: 4 12 12 12 12 12 12 4 12 4 ...
#> $ price : num 7.19 3.99 3.99 3.99 3.99 3.99 7.19 7.19 3.99 7.19 ...
Tipe data tiap kolom sudah sesuai dengan yang diinginkan.
#parsing column
steam_parse <- steam_clean %>%
separate(col = platforms, into = c('windows', 'mac','linux'),sep = ";") %>%
separate(col = categories, into = c('categories1','categories2'),sep = ";") %>%
separate(col = steamspy_tags, into = c('steamtags1', 'steamtags2', 'steamtags3'),
sep = ";")
head(steam_parse)Pada kolom windows, mac, dan linux dapat diubah menjadi 1 dan 0 untuk memudahkan analisis.
#changing into 1 and 0
steam_parse$windows <- ifelse(steam_parse$windows == "windows", 1, 0)
steam_parse$mac <- ifelse(steam_parse$mac == "mac", 1, 0)
steam_parse$linux <- ifelse(steam_parse$linux == "linux", 1,0)
head(steam_parse)Proses imputasi dibutuhkan jika terdapat missing values pada kolom.
#check missing value after parsing
colSums(is.na(steam_parse))#> appid name release_date english
#> 0 0 0 0
#> developer publisher windows mac
#> 0 0 0 18402
#> linux required_age categories1 categories2
#> 22452 0 0 6331
#> genres steamtags1 steamtags2 steamtags3
#> 0 0 558 2665
#> achievements positive_ratings negative_ratings average_playtime
#> 0 0 0 0
#> median_playtime owners price
#> 0 0 0
Terdapat missing values untuk kolom mac dan linux yang merupakan hasil parsing dari kolom platforms. Kolom dengan value NA berarti tidak termasuk dalam mac ataupun linux, maka akan diimputasi dengan nilai 0. Untuk steamtag2 dan steamtags3 missing value disebabkan ada games yang hanya memiliki 1 tags saja, dan akan diimputasi dengan notags. Untuk categories2 missing value disebabkan ada games yang hanya memiliki 1 tags saja, dan akan diimputasi dengan nocat.
#fill NA
steam_parse_clean <-
steam_parse %>%
mutate(mac = if_else(is.na(mac), 0, mac)) %>%
mutate(linux = if_else(is.na(linux), 0, linux)) %>%
mutate(steamtags2 = if_else(is.na(steamtags2), 'notags', steamtags2)) %>%
mutate(steamtags3 = if_else(is.na(steamtags3), 'notags', steamtags3))%>%
mutate(categories2 = if_else(is.na(categories2), 'nocat', categories2))
colSums(is.na(steam_parse_clean))#> appid name release_date english
#> 0 0 0 0
#> developer publisher windows mac
#> 0 0 0 0
#> linux required_age categories1 categories2
#> 0 0 0 0
#> genres steamtags1 steamtags2 steamtags3
#> 0 0 0 0
#> achievements positive_ratings negative_ratings average_playtime
#> 0 0 0 0
#> median_playtime owners price
#> 0 0 0
Sudah tidak ada missing value pada dataset yang akan digunakan.
Kolom yang merupakan hasil dari parsing belum disesuaikan tipe datanya, dan harus diubah ke tipe data yang lebih sesuai.
#changing datatypes from parsing
steam_parse_final <- steam_parse_clean %>%
mutate_at(
vars(
windows,
mac,
linux,
steamtags1,
steamtags2,
steamtags3,
categories1,
categories2
), as.factor
)
steam_parse_finalsteam_parse_final %>%
str()#> 'data.frame': 27075 obs. of 23 variables:
#> $ appid : int 10 20 30 40 50 60 70 80 130 220 ...
#> $ name : chr "Counter-Strike" "Team Fortress Classic" "Day of Defeat" "Deathmatch Classic" ...
#> $ release_date : Date, format: "2000-11-01" "1999-04-01" ...
#> $ english : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
#> $ developer : chr "Valve" "Valve" "Valve" "Valve" ...
#> $ publisher : chr "Valve" "Valve" "Valve" "Valve" ...
#> $ windows : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
#> $ mac : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
#> $ linux : Factor w/ 2 levels "0","1": 2 2 2 2 2 2 2 2 2 2 ...
#> $ required_age : Factor w/ 6 levels "0","3","7","12",..: 1 1 1 1 1 1 1 1 1 1 ...
#> $ categories1 : Factor w/ 23 levels "Captions available",..: 11 11 11 11 16 11 16 16 16 16 ...
#> $ categories2 : Factor w/ 26 levels "Captions available",..: 15 15 25 15 12 15 12 12 13 19 ...
#> $ genres : Factor w/ 1552 levels "Accounting;Animation & Modeling;Audio Production;Design & Illustration;Education;Photo Editing;Software Trainin"| __truncated__,..: 3 3 3 3 3 3 3 3 3 3 ...
#> $ steamtags1 : Factor w/ 206 levels "1980s","1990's",..: 8 8 74 8 74 8 74 8 74 74 ...
#> $ steamtags2 : Factor w/ 284 levels "1980s","1990's",..: 88 88 282 88 10 88 43 88 10 10 ...
#> $ steamtags3 : Factor w/ 323 levels "1980s","1990's",..: 173 173 173 173 239 173 14 173 239 239 ...
#> $ achievements : int 0 0 0 0 0 0 0 0 0 33 ...
#> $ positive_ratings: int 124534 3318 3416 1273 5250 2758 27755 12120 3822 67902 ...
#> $ negative_ratings: int 3339 633 398 267 288 684 1100 1439 420 2419 ...
#> $ average_playtime: int 17612 277 187 258 624 175 1300 427 361 691 ...
#> $ median_playtime : int 317 62 34 184 415 10 83 43 205 402 ...
#> $ owners : Factor w/ 13 levels "0-20000","100000-200000",..: 4 12 12 12 12 12 12 4 12 4 ...
#> $ price : num 7.19 3.99 3.99 3.99 3.99 3.99 7.19 7.19 3.99 7.19 ...
Tahap ini akan membantu memahami atau mencari insight dari dataset.
summary(steam_parse_final)#> appid name release_date english
#> Min. : 10 Length:27075 Min. :1997-06-30 0: 511
#> 1st Qu.: 401230 Class :character 1st Qu.:2016-04-04 1:26564
#> Median : 599070 Mode :character Median :2017-08-08
#> Mean : 596204 Mean :2016-12-31
#> 3rd Qu.: 798760 3rd Qu.:2018-06-06
#> Max. :1069460 Max. :2019-05-01
#>
#> developer publisher windows mac linux
#> Length:27075 Length:27075 0: 5 0:19013 0:22452
#> Class :character Class :character 1:27070 1: 8062 1: 4623
#> Mode :character Mode :character
#>
#>
#>
#>
#> required_age categories1 categories2
#> 0 :26479 Single-player :25678 Steam Achievements :10769
#> 3 : 11 Multi-player : 774 nocat : 6331
#> 7 : 12 Online Multi-Player: 272 Multi-player : 3200
#> 12: 73 Local Multi-Player : 88 Steam Trading Cards : 1222
#> 16: 192 Steam Achievements : 46 Partial Controller Support: 957
#> 18: 308 MMO : 44 Online Multi-Player : 942
#> (Other) : 173 (Other) : 3654
#> genres steamtags1 steamtags2
#> Action;Indie : 1852 Action :5579 Indie :7255
#> Casual;Indie : 1482 Indie :4713 Action :3286
#> Action;Adventure;Indie: 1229 Adventure :3176 Casual :3151
#> Adventure;Indie : 1170 Early Access:2955 Adventure :2714
#> Action;Casual;Indie : 1004 Casual :2394 Strategy :1359
#> Action : 843 Strategy :1927 Simulation:1151
#> (Other) :19495 (Other) :6331 (Other) :8159
#> steamtags3 achievements positive_ratings negative_ratings
#> Indie : 4264 Min. : 0.00 Min. : 0 Min. : 0
#> notags : 2665 1st Qu.: 0.00 1st Qu.: 6 1st Qu.: 2
#> Casual : 2660 Median : 7.00 Median : 24 Median : 9
#> Adventure : 1880 Mean : 45.25 Mean : 1001 Mean : 211
#> Action : 1457 3rd Qu.: 23.00 3rd Qu.: 126 3rd Qu.: 42
#> Simulation: 1220 Max. :9821.00 Max. :2644404 Max. :487076
#> (Other) :12929
#> average_playtime median_playtime owners price
#> Min. : 0.0 Min. : 0.0 0-20000 :18596 Min. : 0.000
#> 1st Qu.: 0.0 1st Qu.: 0.0 20000-50000 : 3059 1st Qu.: 1.690
#> Median : 0.0 Median : 0.0 50000-100000 : 1695 Median : 3.990
#> Mean : 149.8 Mean : 146.1 100000-200000 : 1386 Mean : 6.078
#> 3rd Qu.: 0.0 3rd Qu.: 0.0 200000-500000 : 1272 3rd Qu.: 7.190
#> Max. :190625.0 Max. :190625.0 500000-1000000: 513 Max. :421.990
#> (Other) : 554
Informasi yang diperoleh dari hasil summary adalah sebagai berikut:
indie mendapatkan jumlah terbanyak. Hal ini mungkin menandakan banyaknya developer/publisher independent pada platform Steam.Salah satu indikasi sebuah games yang menarik atau bagus adalah jumlah owners yang banyak dan positive ratings yang tinggi.
a <- steam_parse_final %>%
select(name, positive_ratings, owners) %>%
group_by(owners) %>%
arrange(desc(positive_ratings)) %>%
head(15) %>%
ggplot(mapping = aes(x = positive_ratings,
y = reorder(name, positive_ratings),
text = glue("Total Positive Ratings:{positive_ratings}"))) +
geom_col(aes(fill = owners))+
labs(title = "Highest Positive Ratings Games",
x = "Positive Ratings",
y = "Game Title")+
theme_minimal()+
scale_fill_brewer(palette = "Set3")
ggplotly(a, tooltip = "text")Dari visualisasi menunjukan Counter Strike: Global Offensive mendapatkan positive ratings sangat tinggi walaupun jumlah owners tidak sebanyak Dota 2. Dota 2 adalah games dengan jumlah owners terbanyak.
Kita akan memeriksa bagaimana persebaran data dari pemilik games.
b <- steam_parse_final %>%
group_by(owners) %>%
summarise(count = n()) %>%
ggplot(mapping = aes(y = reorder(owners, count),
x = count,
text = glue("Total Owners:{count}"))) +
geom_col(fill = "dodgerblue3")+
labs(title = "Owners Count",
x = "Total Count",
y = "Owners Range")+
theme_minimal()
ggplotly(b, tooltip = "text")Rentang pemilik mayoritas games ada pada angka 0 - 20 ribu. Hanya beberapa games saja yang dimiliki lebih dari 5 juta player.
Catatan: Kita dapat memfilter data lebih lanjut untuk mendapatkan games dengan pemilik pada rentang diatas 5 juta player dan memberi label data tersebut sebagai game populer.
Beberapa games dapat dimainkan hanya dengan platform operating system tertentu saja, tapi seperti yang kita tahu secara umum operating system Windows hampir dapat memainkan seluruh games.
steam_clean %>%
group_by(platforms) %>%
summarise(count = n())Mayoritas games dapat dimainkan oleh windows, dan hanya sedikit game yang hanya dapat dimainkan pada platform linux saja atau mac saja.
Beberapa games harus dibeli terlebih dahulu sebelum dapat kita mainkan. Games dengan harga 0 berarti dapat dimainkan secara gratis, namun games yang memiliki data harga maka harus dibeli dahulu.
#membuat kolom keterangan tambahan
steam_parse_final$details <- ifelse(steam_parse_final$price == 0.00, "Free","Purchase")
steam_parse_final %>%
group_by(details) %>%
summarise(count = n())Terdapat 2560 games yang gratis, dan 24515 games yang harus dibeli jika ingin dimainkan. Lalu apakah ada perbedaan perilaku dalam bermain antara games gratis dengan games yang dibeli? Kita akan melihat dari sisi playtime.
steam_parse_final %>%
group_by(details) %>%
summarise(playtime = mean(median_playtime))Secara rata-rata dapat kita lihat bahwa durasi bermain (playtime) lebih tinggi pada games yang gratis dibanding games yang berbayar. Tapi karena pendekatan yang kita gunakan adalah rata-rata, dan jumlah games antara free dan purchase sangatlah timpang (beda jauh), maka kesimpulan ini masih perlu ditelaah kembali.
Berikut adalah rencana tampilan dashboard yang akan dibuat. Dashboard akan berisi 3 menu utama, yaitu :