Call of Duty merupakan salah satu permainan populer yang sudah ada sejak console playstation 2, dengan berkembangnya jaman Call of Duty (COD) mulai masuk ke dalam ranah yang lebih luas yaitu secara online. Hal tersebut memberikan kenyamanan pemain untuk berinteraksi dengan pemain lainnya. Perkembangan game yang sangat cepat juga memunculkan kompetisi baru bertema game online. Saat ini terdapat beberapa tim yang sering berkompetisi pada permainan yang memiliki kemiripan tipe permainan dengan COD. Sebagai salah satu tim e-sport sangat penting untuk dapat merekrut pemain yang memang diatas rata-rata pemain lain untuk memiliki kontrak profesional. Sebagai data scientist, kebutuhan dari tim e-sport tersebut dapat dibantu oleh machine learning untuk mengelompokkan permainan suatu pemain sehingga tim tersebut dapat memilih pemain yang dapat mewakili dalam suatu kompetisi.
Data berisi beberapa kolom penting untuk mengelompokkan pemain yang berada diatas rata-rata antara lain
Sebelum mengolah data kita perlu memanggil library dan package yang nantinya kita gunakan dalam analisis dan membuat machine learning.
library(dplyr)
library(tidyverse)
library(cluster)
library(factoextra)
library(GGally)
library(scales)
library(cowplot)
library(FactoMineR)
library(factoextra)
library(plotly)Pertama kita harus memanggil data dan melihat struktur dari data yang kita miliki.
cod <- read.csv("cod.csv")
glimpse(cod)## Rows: 1,558
## Columns: 19
## $ name <chr> "RggRt45#4697369", "JohniceRex#9176033", "bootybootykil~
## $ wins <int> 0, 0, 0, 3, 0, 684, 4, 186, 741, 26, 0, 0, 188, 0, 15, ~
## $ kills <int> 0, 0, 66, 2, 2, 27011, 162, 1898, 21803, 349, 0, 26, 19~
## $ kdRatio <dbl> 0.0000000, 0.0000000, 1.0312500, 0.4000000, 0.2000000, ~
## $ killstreak <int> 0, 0, 0, 0, 0, 18, 4, 13, 26, 7, 0, 0, 22, 0, 7, 10, 17~
## $ level <int> 1, 1, 9, 1, 1, 177, 6, 37, 185, 12, 1, 6, 53, 1, 5, 40,~
## $ losses <int> 0, 0, 0, 0, 0, 10, 2, 7, 29, 4, 0, 0, 4, 0, 4, 9, 11, 1~
## $ prestige <int> 0, 110, 110, 0, 110, 110, 0, 2, 111, 0, 0, 110, 57, 0, ~
## $ hits <int> 0, 0, 0, 0, 0, 98332, 568, 5111, 81361, 996, 0, 0, 3333~
## $ timePlayed <int> 0, 7, 32, 3, 5, 1366, 8, 550, 2442, 44, 0, 37, 409, 1, ~
## $ headshots <int> 0, 0, 16, 0, 1, 5113, 35, 485, 3894, 40, 0, 3, 536, 0, ~
## $ averageTime <dbl> 0.000000, 7.000000, 32.000000, 3.000000, 5.000000, 2.32~
## $ gamesPlayed <int> 0, 0, 0, 0, 0, 588, 4, 150, 864, 15, 0, 0, 25, 0, 6, 12~
## $ assists <int> 0, 0, 1, 0, 0, 6063, 68, 488, 4029, 138, 0, 4, 150, 0, ~
## $ misses <int> 0, 0, 0, 0, 0, 305319, 4836, 39978, 327230, 4844, 0, 0,~
## $ xp <int> 0, 700, 48300, 1150, 1000, 3932335, 24485, 458269, 4269~
## $ scorePerMinute <dbl> 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 255.67204,~
## $ shots <int> 0, 0, 0, 0, 0, 403651, 5404, 45089, 408591, 5840, 0, 0,~
## $ deaths <int> 0, 16, 64, 5, 10, 25321, 256, 3332, 21032, 786, 0, 77, ~
kita memilki 19 kolom dengan satu kolom nama yang bersifat character sedangkan yang lainnya numeric. Tipe data yang kita lihat sudah sesuai dengan apa yang kita butuhkan sehingga tidak diperlukan pengubahan tipe data. Namun sebelum menggunakan data kita harus memastikan data tidak memiliki nilai NA.
colSums(is.na(cod))## name wins kills kdRatio killstreak
## 0 0 0 0 0
## level losses prestige hits timePlayed
## 0 0 0 0 0
## headshots averageTime gamesPlayed assists misses
## 0 0 0 0 0
## xp scorePerMinute shots deaths
## 0 0 0 0
Kita tidak menemukan adanya nilai NA pada data kita, oleh karena itu kita dapat melakukan analisis dan eksploratory data sebelum membuat machine learning yang membantu mengelompokan dan mengidentifikasi pemain yang memiliki potensi menjadi pemain profesional.
Mari kita lakukan sedikit eksploratori dan analisis data. Orang yang memiliki permainan yang baik pasti memiliki tingkat kills tinggi dan death yang rendah sehingga bisa kita lihat dari kdRation. Kita urutkan pemain menurut kdRatio yang nanti dapat kita pastikan dalam machine learning berada pada kelompok yang pemain diatas rata-rata.
cod_kd <- cod[order(cod$kdRatio, decreasing = T),]
cod_kd %>% head(10)ggplot(cod_kd[1:10,], aes(x = kdRatio, y = reorder(name, kdRatio))) +
geom_col(aes(fill = kdRatio))+
scale_fill_gradient(high = "#173F5f",
low = "#3caea3") +
geom_label(mapping = aes(label = kdRatio),
data = cod_kd[1:3,],
nudge_x = 0.15,
size = 4) +
labs(
title = "Top 10 Pemain",
subtitle = "Berdasarkan nilai Kill Death Ratio",
y = "Nama Pemain"
) +
geom_vline(data = cod_kd, aes(xintercept = mean(kdRatio)))Dari grafik tersebut terlihat bahwa akun dengan nama Lucky, Shadow9World, dan black bird memiliki kdRatio paling tinggi dibanding pemain lain. Sedangkan garis hitam menunjukkan rata-rata kdRatio semua pemain.
hist(cod$timePlayed)Pada histogram tersebut terlihat jelas tidak banyak pemain yang bermain lebih dari 2000 jam dan paling banyak berada pada kisaran 0-400 jam saja.
plot(cod$gamesPlayed, cod$level)Kita pasti berpikir bahwa lamanya waktu bermain juga seiring dengan tingginya level yang dimiliki pemain, namun haltersebut juga berkaitan pada cara bermain dan jumlah kemenangan pemain untuk menambah xp setiap levelnya. Terdapat salah satu akun yang memiliki waktu bermain paling tinggi (>3000 jam) namun levelnya tidak terlalu tinggi dibandingkan beberapa pemain yang bermain yang di dalam persebaran rata-rata (< 1000 jam) namun memiliki level yang lebih tinggi atau setara.
boxplot(cod$kdRatio)Sebelumnya kita telah membuat urutan 10 pemain tertinggi dalam kdRatio, mari kita lihat persebarannya dalam boxplot. Tentu beberapa diantara 10 pemain sebelumnya menjadi outlier tersebut. Rerata pemain memiliki kdRatio dibawah 1.
hist(cod$killstreak)Dari histogram killstreak kita dapat mengetahui bahwa rerata pemain memiliki killstreak diantara 0 - 20, sedangkan beberapa orang yang lebih baik bermainnya memiliki killstreak lebih dari 20.
ggplot(cod, aes(x = kills, y = deaths, size = gamesPlayed)) +
geom_point(alpha = 0.5) + theme_minimal() +
labs(title = "Kills vs Deaths")Pada grafik terhilat bahwa Kills yang meningkat juga diikuti oleh deaths yang meningkat dan pada tingkatan yang tinggi menunjukkan banyak permainan yang sudah dijalani pemain. Salah satu pemain denga kills tertinggi memiliki deaths yang lebih rendah dibanding beberapa pemain dengan kills sebanyak 6000. Dari grafik tersebut juga terlihat persebaran yang jelas antara pemain yang memiliki kemampuan bermain baik berdasarkan jumlah kills maupun deaths. Kita ingin mengelompokkan minimal 3 kelompok pemain dengan target utama mendapatkan pemain-pemain yang memiliki kemampuan diatas rata-rata
Setelah melakukan eksploratori dan analisis data kita mendapat informasi yang sangat beragam, untuk menjawab tujuan kita untuk menemukan pemain dengan kemampuan diatas rata-rata maka kita akan membuat machine learning secara unsupervised dari semua data. Sebelumnya kita perlu melakukan “scaling” atau penyamaan sebaran nilai sehingga memudahkan model dalam mempelajari data.
cod_s <- cod %>% remove_rownames %>% column_to_rownames(var="name") %>%
scale()Setelah proses “scaling” maka kita ingin melihat rekomendasi berdasarkan grafik untuk melihat jumlah kelompok yang bisa kita bedakan sebagai landasan untuk mesin kita.
fviz_nbclust(cod_s,
FUNcluster = kmeans,
method = "wss")seperti kita lihat dari grafik bahwa secara optimal kita dapat membagi menjadi 6 kelompok berbeda untuk mendapatkan 6 kelompok dengan ciri-ciri yang berbeda. Namun berdasarkan apa yang kita ingin ketahui dari data tersebut, kita ingin mengelompokkan menjadi 3 kelompok saja. Kita buat kedua model
kita melakukan pengelompokkan data dengan rekomendasi jumlah kelompok 5 terlebih dahulu.
cod_cl <- kmeans(cod_s, centers = 6)
cod$clu <- cod_cl$cluster
cod %>%
group_by(clu) %>%
summarise_all(mean)## Warning in mean.default(name): argument is not numeric or logical: returning NA
## Warning in mean.default(name): argument is not numeric or logical: returning NA
## Warning in mean.default(name): argument is not numeric or logical: returning NA
## Warning in mean.default(name): argument is not numeric or logical: returning NA
## Warning in mean.default(name): argument is not numeric or logical: returning NA
## Warning in mean.default(name): argument is not numeric or logical: returning NA
Dari clustering kita dapat kategorikan menjadi 6, dari keenam kelompok terdapat satu kelompok yang paling menonjol yaitu kelompok nomor 5 dengan kdRatio dan killstreak paling menonjol dibanding kelompok lain.
fviz_cluster(object = cod_cl,
data = cod_s)Selanjutnya kita coba menggunakan k dengan nilai 3 sesuai dengan kebutuhan kita ingin mengelompokkan pemain yang berada diatas rata-rata, pemain biasa, dan pemain baru.
cod_cl_1 <- kmeans(cod_s, centers = 3)
cod$cl1 <- cod_cl_1$cluster
cod %>%
group_by(cl1) %>%
select(-20) %>%
summarise_all(mean)## Warning in mean.default(name): argument is not numeric or logical: returning NA
## Warning in mean.default(name): argument is not numeric or logical: returning NA
## Warning in mean.default(name): argument is not numeric or logical: returning NA
Kelompok 1 menunjukkan nilai kdRatio, killstreak, level, dan wins paling tinggi dibanding kelompok lain sedangkan kelompok 2 memiliki nilai terendah di semua kriteria kecuali averageTime. Dari hal tersebut kita melihat bahwa kelompok 1 memiliki kemampuan yang lebih baik dengan jem terbang bermain yang juga lebih tinggi sehingga dapat dikatakan berpengalaman. sedangkan pemain baru dikategorikan pada kelompok 2 sedangkan pemain yang biasa berada pada kelompok 3.
fviz_cluster(object = cod_cl_1,
data = cod_s)Dari kedua hasil k-means terlihat bahwa pembagian cluster berdasarkan rekomendasi grafik (k=6) dapat membagi kelompok dengan baik sehingga memiliki karakter-karater spesifik. Dengan begitu kita dapat melihat manakah kelompok yang memenuhi persyaratan kita untuk menjadi pemain profesional.
Selanjutnya kita akan mencoba melakukan PCA yaitu salah satu tahap untuk mereduksi dimensi data namun tetap dapat mengambil informasi sebanyak-banyaknya.
cod_pca_2 <- PCA(cod %>% select(c(-name, -clu, -cl1)), scale.unit = T, ncp = 18, graph = F,
quali.sup = 18)
summary(cod_pca_2)##
## Call:
## PCA(X = cod %>% select(c(-name, -clu, -cl1)), scale.unit = T,
## ncp = 18, quali.sup = 18, graph = F)
##
##
## Eigenvalues
## Dim.1 Dim.2 Dim.3 Dim.4 Dim.5 Dim.6 Dim.7
## Variance 11.211 1.458 1.411 0.717 0.509 0.460 0.435
## % of var. 65.949 8.574 8.297 4.217 2.991 2.707 2.556
## Cumulative % of var. 65.949 74.523 82.821 87.038 90.029 92.736 95.292
## Dim.8 Dim.9 Dim.10 Dim.11 Dim.12 Dim.13 Dim.14
## Variance 0.307 0.246 0.089 0.044 0.041 0.023 0.021
## % of var. 1.807 1.449 0.524 0.256 0.241 0.137 0.121
## Cumulative % of var. 97.099 98.548 99.072 99.328 99.569 99.707 99.828
## Dim.15 Dim.16 Dim.17
## Variance 0.018 0.012 0.000
## % of var. 0.104 0.068 0.000
## Cumulative % of var. 99.932 100.000 100.000
##
## Individuals (the 10 first)
## Dist Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3
## 1 | 2.762 | -2.250 0.029 0.664 | -0.733 0.024 0.070 | -1.319
## 2 | 2.862 | -1.962 0.022 0.470 | -1.244 0.068 0.189 | -0.220
## 3 | 2.571 | -1.550 0.014 0.364 | -0.662 0.019 0.066 | 1.117
## 4 | 2.389 | -2.106 0.025 0.777 | -0.464 0.009 0.038 | -0.848
## 5 | 2.653 | -1.891 0.020 0.508 | -1.091 0.052 0.169 | -0.005
## 6 | 9.138 | 8.637 0.427 0.894 | -0.218 0.002 0.001 | -1.176
## 7 | 2.317 | -1.515 0.013 0.427 | 1.320 0.077 0.325 | -0.378
## 8 | 1.396 | -0.115 0.000 0.007 | 0.980 0.042 0.493 | -0.323
## 9 | 9.369 | 9.137 0.478 0.951 | 0.341 0.005 0.001 | -0.118
## 10 | 2.171 | -1.377 0.011 0.402 | 1.266 0.071 0.340 | -0.467
## ctr cos2
## 1 0.079 0.228 |
## 2 0.002 0.006 |
## 3 0.057 0.189 |
## 4 0.033 0.126 |
## 5 0.000 0.000 |
## 6 0.063 0.017 |
## 7 0.007 0.027 |
## 8 0.005 0.053 |
## 9 0.001 0.000 |
## 10 0.010 0.046 |
##
## Variables (the 10 first)
## Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3 ctr
## wins | 0.931 7.731 0.867 | -0.075 0.383 0.006 | -0.074 0.383
## kills | 0.972 8.433 0.945 | -0.077 0.409 0.006 | -0.130 1.207
## kdRatio | 0.507 2.290 0.257 | 0.370 9.415 0.137 | 0.581 23.912
## killstreak | 0.592 3.128 0.351 | 0.435 12.987 0.189 | 0.300 6.383
## level | 0.920 7.548 0.846 | -0.155 1.638 0.024 | 0.181 2.323
## losses | 0.724 4.671 0.524 | 0.319 6.964 0.102 | 0.231 3.786
## prestige | 0.451 1.814 0.203 | -0.269 4.955 0.072 | 0.590 24.638
## hits | 0.945 7.966 0.893 | -0.031 0.064 0.001 | -0.197 2.749
## timePlayed | 0.927 7.670 0.860 | -0.195 2.618 0.038 | 0.061 0.268
## headshots | 0.958 8.187 0.918 | -0.072 0.355 0.005 | -0.098 0.681
## cos2
## wins 0.005 |
## kills 0.017 |
## kdRatio 0.337 |
## killstreak 0.090 |
## level 0.033 |
## losses 0.053 |
## prestige 0.348 |
## hits 0.039 |
## timePlayed 0.004 |
## headshots 0.010 |
##
## Supplementary categories (the 10 first)
## Dist Dim.1 cos2 v.test Dim.2 cos2 v.test
## 0 | 2.742 | -2.243 0.669 -10.491 | -0.729 0.071 -9.455 |
## 1 | 2.229 | -2.040 0.837 -2.449 | -0.288 0.017 -0.960 |
## 2 | 2.292 | -2.066 0.812 -4.150 | -0.510 0.050 -2.844 |
## 3 | 2.336 | -2.088 0.799 -1.876 | -0.604 0.067 -1.505 |
## 4 | 2.265 | -2.047 0.817 -2.608 | -0.628 0.077 -2.219 |
## 5 | 2.347 | -2.100 0.800 -1.989 | -0.530 0.051 -1.392 |
## 6 | 2.197 | -2.025 0.849 -2.353 | -0.499 0.052 -1.608 |
## 7 | 2.285 | -2.061 0.813 -1.745 | -0.511 0.050 -1.199 |
## 8 | 2.389 | -2.113 0.782 -1.673 | -0.639 0.072 -1.403 |
## 9 | 2.218 | -2.020 0.829 -1.913 | -0.513 0.053 -1.346 |
## Dim.3 cos2 v.test
## 0 -1.297 0.224 -17.101 |
## 1 -0.736 0.109 -2.492 |
## 2 -0.704 0.094 -3.985 |
## 3 -0.813 0.121 -2.060 |
## 4 -0.619 0.075 -2.223 |
## 5 -0.835 0.126 -2.229 |
## 6 -0.640 0.085 -2.096 |
## 7 -0.800 0.123 -1.910 |
## 8 -0.856 0.128 -1.911 |
## 9 -0.537 0.059 -1.435 |
Kita ingin menggunakan dimensi yang masih mengandung data lebih dari 90%. sehingga kita menggunakan dimensi 1 sampai 5. Grafik berikut akan menunjukkan seberapa banyak informasi yang terseimpan dari tiap dimensi.
fviz_eig(cod_pca_2, addlabels = T, main = "Variance explained by each dimensions")dimensi 1 selalu mengandung paling banyak informasi namun untuk memenuhi syarat yang kita gunakan yaitu minimal 90% harus menggunakan dimensi 1 hingga 5.
Setelah kita tentukan jumlah dimensi, kemudian kita memasukan kolom cluster yang berasal dari proses K-means untuk mempermudah kita mengelompokkan data.
df_pca <- data.frame(cod_pca_2$ind$coord[, 1:5]) %>% bind_cols(cluster = as.factor(cod$clu)) %>%
select(cluster, 1:5)
df_pcaDengan prediktor yang sudah direduksi dimensinya kita dapat melihat kontribusi dari tiap prediktor terhadap dimensi yang kita ambil.
fviz_pca_var(cod_pca_2, select.var = list(contrib = 18), col.var = "contrib",
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"), repel = TRUE)## Warning: ggrepel: 8 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps
Grafik menarik tersebut menunjukkan beberapa prediktor yang paling berkontribusi/mempengaruhi. PC2 dipengaruhi oleh averageTime, prestige, scorePerMinute, killstreak, kdRatio, dan losses sedangkan cariabel lain mempengaruhi PC1. Untuk melihat lebih jelas kita dapat membuat histogram seperti berikut ini.
fviz_cos2(cod_pca_2, choice = "var", fill = "cos2") + scale_fill_viridis_c(option = "A")Yang paling berperan dalam hasil PCA kita adalah kolom kills, headshots, shots, misses, hits, assists, wins, gamesPLayed, level, timePlayed, dan xp sedangkan yang berkontribusi paling kecil adalah averageTime. Berdasarkan data kita juga dapat melihat bahwa kolom yang kita gunakan sebagai acuan menentukan level (kdRatio) tidak memiliki kontribusi yang signifikan.
fviz_cluster(object = cod_cl, data = cod[,-1], labelsize = 0) + theme_minimal()Berdasarkan label yang berasal dari k-means dan hasil PCA didapatkan pengelompokkan yang lebih baik secara visual dibandingkan plot dari k-means sebelumnya. Dari hasil k-means, nilai win tertinggi dimiliki oleh cluster 5 yang tergambarkan berwarna biru pada grafik.
Grafik berikut membantu kita melihat jelassecara 3 dimensi persebaran dan pengelompokan data kita.
plot_ly(df_pca, x = ~Dim.1, y = ~Dim.2, z = ~Dim.3, color = ~cluster, colors = c("black", "red", "yellow", "orange",
"green", "blue")) %>% add_markers() %>% layout(scene = list(xaxis = list(title = "Dim.1"),
yaxis = list(title = "Dim.2"), zaxis = list(title = "Dim.3")))Dari data serta pengolahan dengan metode k-means serta PCA dapat kita simpulkan bahwa
Pengelompokkan paling baik dibagi menjadi 6 dengan dapat mendefinisikan salah satu cluster memiliki potensi paling tinggi untuk menjadi pemain profesional.
Berdasarkan pengelompokkan yang sudah dilakukan, kelompok dengan potensipaling tinggi dapat menjadi pemain profesional adalah kelompok 5 dengan variable wins, Kills, serta kdRatio tertinggi.
Penggunaan metode PCA membantu kita mereduksi dari sebelumnya 18 kolom menjadi 5 kolom baru yang dapat mencakup 90 % data. Dengan metode PCA kita dapat melihat lebih jelas pengelompokan yang terbentuk.