Libraries used in the analysis:
library(dplyr)
##
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(FactoMineR)
## Warning: package 'FactoMineR' was built under R version 4.4.3
library(factoextra)
## Warning: package 'factoextra' was built under R version 4.4.3
## Cargando paquete requerido: ggplot2
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(ggplot2)
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.4.3
## corrplot 0.95 loaded
library(reshape2)
## Warning: package 'reshape2' was built under R version 4.4.3
library(NbClust)
library(grid)
library(gridExtra)
## Warning: package 'gridExtra' was built under R version 4.4.3
##
## Adjuntando el paquete: 'gridExtra'
## The following object is masked from 'package:dplyr':
##
## combine
library(cluster)
library(tidyr)
##
## Adjuntando el paquete: 'tidyr'
## The following object is masked from 'package:reshape2':
##
## smiths
Functions created in order to make more eficient the analysis process.
Function made to show a general vision of a dataframe.
show_df <- function(df) {
start <- head(df, 4)
finish <- tail(df, 4)
dots <- as.data.frame(matrix("...", nrow = 1, ncol = ncol(df)))
colnames(dots) <- colnames(df)
rownames(dots) <- ""
s_df <- rbind(start, dots, finish)
print(s_df)
}
Function made in order to prepare the dataframe to do a PCA. Categorical variables are encoded as dummy variables and numerical variables are aggregated using the mean, grouped by name. After all, the new dataframe has been centered and scaled.
prepare_df <- function(df, vgroup) {
df <- df[order(df[[vgroup]]), ]
new_df <- data.frame(namesgroup = df[[vgroup]])
num_vars <- names(df)[sapply(df, is.numeric)]
cat_vars <- names(df)[sapply(df, function(x) is.factor(x) || is.character(x))]
cat_vars <- setdiff(cat_vars, vgroup)
for (cv in cat_vars) {
formula <- as.formula(paste0("~", cv, " - 1"))
vdummy <- model.matrix(formula, data = df)
new_df <- cbind(new_df, vdummy)
}
new_df <- unique(new_df)
for (nv in num_vars) {
vmean <- df %>%
group_by(across(all_of(vgroup))) %>%
summarise(mean_value = mean(.data[[nv]])) %>%
rename(!!paste0("champion_", nv) := mean_value)
vmean <- vmean[, !names(vmean) %in% vgroup]
new_df <- cbind(new_df, vmean)
}
rownames(new_df) <- new_df[, "namesgroup"]
new_df <- new_df[, !names(new_df) %in% "namesgroup"]
prepared_df <- scale(new_df, center = TRUE, scale = TRUE)
prepared_df <- data.frame(prepared_df)
return(prepared_df)
}
To divide champions according to their playstyle, using their descriptors and statistics.
Prepare the dataframe and reduce the dimensionality of the data.
Cluster champions according to their playstyle.
Describe the profiles that make up each cluster and rank the champions according to their performance.
The dataset obtained in the cleaning process is loaded.
lol_df <- read.csv("D:/UPV/2º/Proyecto II/lol_dataset.csv")
show_df(lol_df)
## champion_name difficulty herotype alttype resource
## 1 Aatrox 2 Fighter Tank Blood Well
## 2 Aatrox 2 Fighter Tank Blood Well
## 3 Aatrox 2 Fighter Tank Blood Well
## 4 Aatrox 2 Fighter Tank Blood Well
## ... ... ... ... ...
## 5936 Zyra 2 Mage Support Mana
## 5937 Zyra 2 Mage Support Mana
## 5938 Zyra 2 Mage Support Mana
## 5939 Zyra 2 Mage Support Mana
## stats
## 1 {'hp_base': 650, 'hp_lvl': 114, 'mp_base': 0, 'mp_lvl': 0, 'arm_base': 38, 'arm_lvl': 4.8, 'mr_base': 32, 'mr_lvl': 2.05, 'hp5_base': 3, 'hp5_lvl': 0.5, 'mp5_base': 0, 'mp5_lvl': 0, 'dam_base': 60, 'dam_lvl': 5, 'as_base': 0.651, 'as_lvl': 2.5, 'range': 175, 'ms': 345, 'acquisition_radius': 475, 'selection_height': 180, 'selection_radius': 135, 'pathing_radius': 35, 'as_ratio': 0.651000022888183, 'attack_cast_time': 0.300000011920928, 'attack_total_time': 1.51999998092651, 'aram': {'dmg_dealt': 1.05, 'dmg_taken': 1}, 'urf': {'dmg_dealt': 1.15, 'dmg_taken': 0.7}}
## 2 {'hp_base': 650, 'hp_lvl': 114, 'mp_base': 0, 'mp_lvl': 0, 'arm_base': 38, 'arm_lvl': 4.8, 'mr_base': 32, 'mr_lvl': 2.05, 'hp5_base': 3, 'hp5_lvl': 0.5, 'mp5_base': 0, 'mp5_lvl': 0, 'dam_base': 60, 'dam_lvl': 5, 'as_base': 0.651, 'as_lvl': 2.5, 'range': 175, 'ms': 345, 'acquisition_radius': 475, 'selection_height': 180, 'selection_radius': 135, 'pathing_radius': 35, 'as_ratio': 0.651000022888183, 'attack_cast_time': 0.300000011920928, 'attack_total_time': 1.51999998092651, 'aram': {'dmg_dealt': 1.05, 'dmg_taken': 1}, 'urf': {'dmg_dealt': 1.15, 'dmg_taken': 0.7}}
## 3 {'hp_base': 650, 'hp_lvl': 114, 'mp_base': 0, 'mp_lvl': 0, 'arm_base': 38, 'arm_lvl': 4.8, 'mr_base': 32, 'mr_lvl': 2.05, 'hp5_base': 3, 'hp5_lvl': 0.5, 'mp5_base': 0, 'mp5_lvl': 0, 'dam_base': 60, 'dam_lvl': 5, 'as_base': 0.651, 'as_lvl': 2.5, 'range': 175, 'ms': 345, 'acquisition_radius': 475, 'selection_height': 180, 'selection_radius': 135, 'pathing_radius': 35, 'as_ratio': 0.651000022888183, 'attack_cast_time': 0.300000011920928, 'attack_total_time': 1.51999998092651, 'aram': {'dmg_dealt': 1.05, 'dmg_taken': 1}, 'urf': {'dmg_dealt': 1.15, 'dmg_taken': 0.7}}
## 4 {'hp_base': 650, 'hp_lvl': 114, 'mp_base': 0, 'mp_lvl': 0, 'arm_base': 38, 'arm_lvl': 4.8, 'mr_base': 32, 'mr_lvl': 2.05, 'hp5_base': 3, 'hp5_lvl': 0.5, 'mp5_base': 0, 'mp5_lvl': 0, 'dam_base': 60, 'dam_lvl': 5, 'as_base': 0.651, 'as_lvl': 2.5, 'range': 175, 'ms': 345, 'acquisition_radius': 475, 'selection_height': 180, 'selection_radius': 135, 'pathing_radius': 35, 'as_ratio': 0.651000022888183, 'attack_cast_time': 0.300000011920928, 'attack_total_time': 1.51999998092651, 'aram': {'dmg_dealt': 1.05, 'dmg_taken': 1}, 'urf': {'dmg_dealt': 1.15, 'dmg_taken': 0.7}}
## ...
## 5936 {'hp_base': 574, 'hp_lvl': 93, 'mp_base': 418, 'mp_lvl': 25, 'arm_base': 29, 'arm_lvl': 4.2, 'mr_base': 30, 'mr_lvl': 1.3, 'hp5_base': 5.5, 'hp5_lvl': 0.5, 'mp5_base': 7, 'mp5_lvl': 0.8, 'dam_base': 53, 'dam_lvl': 3.2, 'as_base': 0.681, 'as_lvl': 2.11, 'range': 575, 'ms': 340, 'acquisition_radius': 575, 'selection_height': 120, 'selection_radius': 120, 'pathing_radius': 35, 'as_ratio': 0.625, 'attack_delay_offset': -0.154166668653488, 'missile_speed': 1700, 'aram': {'dmg_dealt': 0.9, 'dmg_taken': 1.05, 'ability_haste': -10}, 'nb': {'dmg_dealt': 0.95, 'dmg_taken': 1.08}}
## 5937 {'hp_base': 574, 'hp_lvl': 93, 'mp_base': 418, 'mp_lvl': 25, 'arm_base': 29, 'arm_lvl': 4.2, 'mr_base': 30, 'mr_lvl': 1.3, 'hp5_base': 5.5, 'hp5_lvl': 0.5, 'mp5_base': 7, 'mp5_lvl': 0.8, 'dam_base': 53, 'dam_lvl': 3.2, 'as_base': 0.681, 'as_lvl': 2.11, 'range': 575, 'ms': 340, 'acquisition_radius': 575, 'selection_height': 120, 'selection_radius': 120, 'pathing_radius': 35, 'as_ratio': 0.625, 'attack_delay_offset': -0.154166668653488, 'missile_speed': 1700, 'aram': {'dmg_dealt': 0.9, 'dmg_taken': 1.05, 'ability_haste': -10}, 'nb': {'dmg_dealt': 0.95, 'dmg_taken': 1.08}}
## 5938 {'hp_base': 574, 'hp_lvl': 93, 'mp_base': 418, 'mp_lvl': 25, 'arm_base': 29, 'arm_lvl': 4.2, 'mr_base': 30, 'mr_lvl': 1.3, 'hp5_base': 5.5, 'hp5_lvl': 0.5, 'mp5_base': 7, 'mp5_lvl': 0.8, 'dam_base': 53, 'dam_lvl': 3.2, 'as_base': 0.681, 'as_lvl': 2.11, 'range': 575, 'ms': 340, 'acquisition_radius': 575, 'selection_height': 120, 'selection_radius': 120, 'pathing_radius': 35, 'as_ratio': 0.625, 'attack_delay_offset': -0.154166668653488, 'missile_speed': 1700, 'aram': {'dmg_dealt': 0.9, 'dmg_taken': 1.05, 'ability_haste': -10}, 'nb': {'dmg_dealt': 0.95, 'dmg_taken': 1.08}}
## 5939 {'hp_base': 574, 'hp_lvl': 93, 'mp_base': 418, 'mp_lvl': 25, 'arm_base': 29, 'arm_lvl': 4.2, 'mr_base': 30, 'mr_lvl': 1.3, 'hp5_base': 5.5, 'hp5_lvl': 0.5, 'mp5_base': 7, 'mp5_lvl': 0.8, 'dam_base': 53, 'dam_lvl': 3.2, 'as_base': 0.681, 'as_lvl': 2.11, 'range': 575, 'ms': 340, 'acquisition_radius': 575, 'selection_height': 120, 'selection_radius': 120, 'pathing_radius': 35, 'as_ratio': 0.625, 'attack_delay_offset': -0.154166668653488, 'missile_speed': 1700, 'aram': {'dmg_dealt': 0.9, 'dmg_taken': 1.05, 'ability_haste': -10}, 'nb': {'dmg_dealt': 0.95, 'dmg_taken': 1.08}}
## rangetype client_positions external_positions damage toughness control
## 1 Melee {'Top'} {'Top'} 3 3 2
## 2 Melee {'Top'} {'Top'} 3 3 2
## 3 Melee {'Top'} {'Top'} 3 3 2
## 4 Melee {'Top'} {'Top'} 3 3 2
## ... ... ... ... ... ...
## 5936 Ranged {'Support'} {'Support'} 3 1 3
## 5937 Ranged {'Support'} {'Support'} 3 1 3
## 5938 Ranged {'Support'} {'Support'} 3 1 3
## 5939 Ranged {'Support'} {'Support'} 3 1 3
## mobility utility style adaptivetype game_duration summoner_level win
## 1 2 2 20 Physical 1431 348 FALSE
## 2 2 2 20 Physical 1635 155 FALSE
## 3 2 2 20 Physical 1681 546 TRUE
## 4 2 2 20 Physical 1448 501 FALSE
## ... ... ... ... ... ... ...
## 5936 1 1 100 Magic 1650 318 FALSE
## 5937 1 1 100 Magic 1508 90 TRUE
## 5938 1 1 100 Magic 1834 136 FALSE
## 5939 1 1 100 Magic 1870 189 TRUE
## team_position kills deaths assists baron_kills dragon_kills gold_earned
## 1 TOP 8 4 5 0 0 11534
## 2 TOP 5 10 3 0 0 9628
## 3 TOP 3 3 6 0 0 11801
## 4 TOP 5 5 1 0 0 9716
## ... ... ... ... ... ... ...
## 5936 UTILITY 1 9 7 0 0 7106
## 5937 UTILITY 2 3 9 0 0 8260
## 5938 UTILITY 4 5 6 0 0 8098
## 5939 UTILITY 7 2 29 0 0 13207
## gold_spent total_damage_dealt total_damage_dealt_to_champions
## 1 11200 132656 20716
## 2 9525 117163 23238
## 3 11125 167169 28334
## 4 8550 111681 17372
## ... ... ...
## 5936 6625 48530 18850
## 5937 6900 68126 14811
## 5938 7950 46016 13094
## 5939 11775 114357 36594
## physical_damage_dealt_to_champions magic_damage_dealt_to_champions
## 1 17114 2311
## 2 18608 4629
## 3 23648 4660
## 4 14762 2610
## ... ...
## 5936 1483 16834
## 5937 1209 12790
## 5938 889 11309
## 5939 1745 33936
## true_damage_dealt_to_champions damage_dealt_to_objectives
## 1 1290 4141
## 2 0 3252
## 3 26 7052
## 4 0 4742
## ... ...
## 5936 531 1356
## 5937 810 19087
## 5938 896 1390
## 5939 912 12607
## damage_dealt_to_turrets total_damage_taken physical_damage_taken
## 1 4141 22358 13786
## 2 3252 46330 30331
## 3 3916 33634 12072
## 4 4742 22320 13035
## ... ... ...
## 5936 1109 22507 10524
## 5937 4381 10610 4866
## 5938 191 19810 9915
## 5939 1092 18859 7431
## magic_damage_taken true_damage_taken time_ccing_others vision_score
## 1 6608 1963 16 12
## 2 11197 4801 29 14
## 3 17348 4213 31 18
## 4 7329 1954 19 6
## ... ... ... ...
## 5936 11089 893 56 37
## 5937 5533 209 48 47
## 5938 9350 544 52 18
## 5939 10738 690 64 79
## wards_placed wards_killed solo_tier solo_wins solo_losses flex_tier
## 1 6 1 EMERALD 57 37 GOLD
## 2 10 0 DIAMOND 7 3 DIAMOND
## 3 9 3 PLATINUM 32 26 GOLD
## 4 6 0 MASTER 47 52 EMERALD
## ... ... ... ... ... ...
## 5936 19 3 SILVER 10 16 GOLD
## 5937 19 4 IRON 7 9 IRON
## 5938 7 0 IRON 2 3 IRON
## 5939 26 10 GOLD 4 1 DIAMOND
## flex_wins flex_losses champion_mastery_level champion_mastery_points
## 1 12 2 80 1019510
## 2 6 7 36 362254
## 3 7 5 16 147132
## 4 2 6 84 1213248
## ... ... ... ...
## 5936 12 14 4 15503
## 5937 6 7 32 431758
## 5938 3 2 9 68490
## 5939 20 17 39 465737
## final_abilityPower final_armor final_armorPenPercent final_attackDamage
## 1 0 96 0 309
## 2 0 126 0 279
## 3 38 119 0 363
## 4 0 96 0 261
## ... ... ... ...
## 5936 180 70 0 84
## 5937 202 70 0 87
## 5938 185 78 0 90
## 5939 318 95 0 99
## final_attackSpeed final_ccReduction final_healthMax final_lifesteal
## 1 130 36 2738 0
## 2 151 0 3532 3
## 3 142 40 3641 0
## 4 130 29 2278 0
## ... ... ... ...
## 5936 125 0 2159 0
## 5937 120 0 2109 0
## 5938 123 0 2812 0
## 5939 143 0 3330 0
## final_magicPenPercent final_magicResist final_movementSpeed final_powerMax
## 1 0 81 390 0
## 2 0 59 400 0
## 3 0 131 390 0
## 4 0 131 414 0
## ... ... ... ...
## 5936 0 42 385 1514
## 5937 0 42 385 964
## 5938 0 46 385 941
## 5939 8 51 390 1029
Relevant variables for the objective are selected.
# Variables related to champions in the dataset
champion_variables <- c("champion_name", "resource", "rangetype", "adaptivetype",
"damage", "toughness", "control", "mobility", "utility")
# Variables related to games and stats in the dataset
stats_variables <- c("kills", "assists", "time_ccing_others", "vision_score", "gold_earned",
"total_damage_dealt_to_champions", "total_damage_taken",
"damage_dealt_to_objectives", "damage_dealt_to_turrets",
"final_attackDamage", "final_abilityPower", "final_attackSpeed",
"final_ccReduction", "final_healthMax", "final_armor", "final_magicResist")
champion_stats_variables <- union(champion_variables, stats_variables)
champion_stats_df <- lol_df[, champion_stats_variables]
show_df(champion_stats_df)
## champion_name resource rangetype adaptivetype damage toughness control
## 1 Aatrox Blood Well Melee Physical 3 3 2
## 2 Aatrox Blood Well Melee Physical 3 3 2
## 3 Aatrox Blood Well Melee Physical 3 3 2
## 4 Aatrox Blood Well Melee Physical 3 3 2
## ... ... ... ... ... ... ...
## 5936 Zyra Mana Ranged Magic 3 1 3
## 5937 Zyra Mana Ranged Magic 3 1 3
## 5938 Zyra Mana Ranged Magic 3 1 3
## 5939 Zyra Mana Ranged Magic 3 1 3
## mobility utility kills assists time_ccing_others vision_score gold_earned
## 1 2 2 8 5 16 12 11534
## 2 2 2 5 3 29 14 9628
## 3 2 2 3 6 31 18 11801
## 4 2 2 5 1 19 6 9716
## ... ... ... ... ... ... ...
## 5936 1 1 1 7 56 37 7106
## 5937 1 1 2 9 48 47 8260
## 5938 1 1 4 6 52 18 8098
## 5939 1 1 7 29 64 79 13207
## total_damage_dealt_to_champions total_damage_taken
## 1 20716 22358
## 2 23238 46330
## 3 28334 33634
## 4 17372 22320
## ... ...
## 5936 18850 22507
## 5937 14811 10610
## 5938 13094 19810
## 5939 36594 18859
## damage_dealt_to_objectives damage_dealt_to_turrets final_attackDamage
## 1 4141 4141 309
## 2 3252 3252 279
## 3 7052 3916 363
## 4 4742 4742 261
## ... ... ...
## 5936 1356 1109 84
## 5937 19087 4381 87
## 5938 1390 191 90
## 5939 12607 1092 99
## final_abilityPower final_attackSpeed final_ccReduction final_healthMax
## 1 0 130 36 2738
## 2 0 151 0 3532
## 3 38 142 40 3641
## 4 0 130 29 2278
## ... ... ... ...
## 5936 180 125 0 2159
## 5937 202 120 0 2109
## 5938 185 123 0 2812
## 5939 318 143 0 3330
## final_armor final_magicResist
## 1 96 81
## 2 126 59
## 3 119 131
## 4 96 131
## ... ...
## 5936 70 42
## 5937 70 42
## 5938 78 46
## 5939 95 51
The dataframe is prepared for the analysis with the function “prepare_df”. The categorical variables, which belong to the champions’ descriptions, will be transformed into dummy variables. Numerical variables will be grouped by “champion_name”, and the mean of all observations for each champion will be calculated. After the above, the data frame will be centered and scaled. In addition, the variable “champion_name” will be used as the name of each row.
prepared_df <- prepare_df(champion_stats_df, "champion_name")
analysis_df <- prepared_df[, !names(prepared_df) %in% c("champion_gold_earned")]
show_df(analysis_df)
## resourceBlood.Well resourceCourage resourceCrimson.Rush
## Aatrox 12.8843297218347 -0.077151674981046 -0.077151674981046
## Ahri -0.077151674981046 -0.077151674981046 -0.077151674981046
## Akali -0.077151674981046 -0.077151674981046 -0.077151674981046
## Akshan -0.077151674981046 -0.077151674981046 -0.077151674981046
## ... ... ...
## Ziggs -0.077151674981046 -0.077151674981046 -0.077151674981046
## Zilean -0.077151674981046 -0.077151674981046 -0.077151674981046
## Zoe -0.077151674981046 -0.077151674981046 -0.077151674981046
## Zyra -0.077151674981046 -0.077151674981046 -0.077151674981046
## resourceEnergy resourceFerocity resourceFlow
## Aatrox -0.191876466725977 -0.077151674981046 -0.109437093062285
## Ahri -0.191876466725977 -0.077151674981046 -0.109437093062285
## Akali 5.18066460160139 -0.077151674981046 -0.109437093062285
## Akshan -0.191876466725977 -0.077151674981046 -0.109437093062285
## ... ... ...
## Ziggs -0.191876466725977 -0.077151674981046 -0.109437093062285
## Zilean -0.191876466725977 -0.077151674981046 -0.109437093062285
## Zoe -0.191876466725977 -0.077151674981046 -0.109437093062285
## Zyra -0.191876466725977 -0.077151674981046 -0.109437093062285
## resourceFrenzy resourceFury resourceGrit
## Aatrox -0.077151674981046 -0.134438064080055 -0.077151674981046
## Ahri -0.077151674981046 -0.134438064080055 -0.077151674981046
## Akali -0.077151674981046 -0.134438064080055 -0.077151674981046
## Akshan -0.077151674981046 -0.134438064080055 -0.077151674981046
## ... ... ...
## Ziggs -0.077151674981046 -0.134438064080055 -0.077151674981046
## Zilean -0.077151674981046 -0.134438064080055 -0.077151674981046
## Zoe -0.077151674981046 -0.134438064080055 -0.077151674981046
## Zyra -0.077151674981046 -0.134438064080055 -0.077151674981046
## resourceHealth resourceHeat resourceMana
## Aatrox -0.109437093062285 -0.077151674981046 -2.2294030804765
## Ahri -0.109437093062285 -0.077151674981046 0.445880616095299
## Akali -0.109437093062285 -0.077151674981046 -2.2294030804765
## Akshan -0.109437093062285 -0.077151674981046 0.445880616095299
## ... ... ...
## Ziggs -0.109437093062285 -0.077151674981046 0.445880616095299
## Zilean -0.109437093062285 -0.077151674981046 0.445880616095299
## Zoe -0.109437093062285 -0.077151674981046 0.445880616095299
## Zyra -0.109437093062285 -0.077151674981046 0.445880616095299
## resourceNone resourceRage resourceShield
## Aatrox -0.174620326001856 -0.109437093062285 -0.077151674981046
## Ahri -0.174620326001856 -0.109437093062285 -0.077151674981046
## Akali -0.174620326001856 -0.109437093062285 -0.077151674981046
## Akshan -0.174620326001856 -0.109437093062285 -0.077151674981046
## ... ... ...
## Ziggs -0.174620326001856 -0.109437093062285 -0.077151674981046
## Zilean -0.174620326001856 -0.109437093062285 -0.077151674981046
## Zoe -0.174620326001856 -0.109437093062285 -0.077151674981046
## Zyra -0.174620326001856 -0.109437093062285 -0.077151674981046
## rangetypeMelee rangetypeRanged adaptivetypeMagic
## Aatrox 0.939338530740863 -0.939338530740863 -0.928174518346596
## Ahri -1.05824214222705 1.05824214222705 1.07097059809223
## Akali 0.939338530740863 -0.939338530740863 -0.928174518346596
## Akshan -1.05824214222705 1.05824214222705 -0.928174518346596
## ... ... ...
## Ziggs -1.05824214222705 1.05824214222705 1.07097059809223
## Zilean -1.05824214222705 1.05824214222705 1.07097059809223
## Zoe -1.05824214222705 1.05824214222705 1.07097059809223
## Zyra -1.05824214222705 1.05824214222705 1.07097059809223
## adaptivetypePhysical champion_damage champion_toughness
## Aatrox 0.928174518346596 0.774385424703707 1.83065336934879
## Ahri -1.07097059809223 0.774385424703707 -0.809258785591955
## Akali 0.928174518346596 0.774385424703707 -0.809258785591955
## Akshan 0.928174518346596 0.774385424703707 -0.809258785591955
## ... ... ...
## Ziggs -1.07097059809223 0.774385424703707 -0.809258785591955
## Zilean -1.07097059809223 -0.655249205518522 -0.809258785591955
## Zoe -1.07097059809223 0.774385424703707 -0.809258785591955
## Zyra -1.07097059809223 0.774385424703707 -0.809258785591955
## champion_control champion_mobility champion_utility
## Aatrox 0.00824715553052613 0.250705079828437 0.795239217269529
## Ahri 0.00824715553052613 1.52702184986412 -0.689207321633591
## Akali -1.37727497359787 1.52702184986412 -0.689207321633591
## Akshan -1.37727497359787 1.52702184986412 0.795239217269529
## ... ... ...
## Ziggs 0.00824715553052613 0.250705079828437 -0.689207321633591
## Zilean 0.00824715553052613 0.250705079828437 2.27968575617265
## Zoe 0.00824715553052613 0.250705079828437 -0.689207321633591
## Zyra 1.39376928465892 -1.02561169020724 -0.689207321633591
## champion_kills champion_assists champion_time_ccing_others
## Aatrox -0.159026760321902 -0.810047803947257 -0.154802630760136
## Ahri -0.1232072593701 -0.244098592270786 -0.354415291838222
## Akali 1.55857150105353 -0.856426214987895 -1.34503038821721
## Akshan 1.16580000193199 -0.820383564122028 -1.33255848837055
## ... ... ...
## Ziggs 0.653837544101415 0.556939832070813 -0.289709182167312
## Zilean -1.75213557183893 2.02117252349667 -0.0944065104221308
## Zoe 1.21731823668224 0.442230358548972 0.659382087138045
## Zyra -0.741447980384434 1.07060210688553 1.53832382536758
## champion_vision_score champion_total_damage_dealt_to_champions
## Aatrox -0.694411818739119 0.526279172116685
## Ahri -0.453211183308094 0.110877810201137
## Akali -0.509627091782893 0.708153142717392
## Akshan -0.698735781349894 0.408753888360733
## ... ...
## Ziggs -0.325073345735362 2.57385232254126
## Zilean 2.05710975927531 -1.76188104497941
## Zoe -0.154107143300923 0.99921989802892
## Zyra 2.09964874329336 0.976150143413274
## champion_total_damage_taken champion_damage_dealt_to_objectives
## Aatrox 0.97613612220722 -0.617475713208985
## Ahri -0.724009521044824 -0.861899182900195
## Akali 0.0696858290972184 -0.888711954312996
## Akshan -0.698422949399065 -0.451534065728636
## ... ...
## Ziggs -0.690772197088214 -0.149970741796532
## Zilean -1.08888873796288 -1.22825306755781
## Zoe -1.04938733284464 -0.949993484290738
## Zyra -0.495894543887284 0.0506811064250639
## champion_damage_dealt_to_turrets champion_final_attackDamage
## Aatrox 0.290659851304982 1.31959872136325
## Ahri -0.282329555836636 -0.917679263156813
## Akali 0.0287674318798189 -0.73742948246733
## Akshan -0.259622084290543 0.870998900434925
## ... ...
## Ziggs 1.76666523576153 -0.862957173706503
## Zilean -1.13741244065152 -1.0218589448223
## Zoe -0.262946421256272 -0.845438148197303
## Zyra -0.888185554881257 -0.96360251803662
## champion_final_abilityPower champion_final_attackSpeed
## Aatrox -0.822765451694239 -0.607880404552245
## Ahri 1.39289953714227 -0.567013757225473
## Akali 1.54129605505782 -0.266891693705877
## Akshan -0.815353784811066 1.12574973470565
## ... ...
## Ziggs 2.16280364100328 -0.78462599711132
## Zilean 0.0366065615195856 -0.875006033085359
## Zoe 1.54241055083768 -0.525606826958317
## Zyra 0.703412391380462 -0.886995221530895
## champion_final_ccReduction champion_final_healthMax champion_final_armor
## Aatrox 1.98675853426468 0.598155111811785 0.0216848040995538
## Ahri -0.511186905904286 -0.819171601525684 -0.601137239856415
## Akali 0.0442963691187498 0.112088327841134 -0.169168740636517
## Akshan 1.07487463392056 -0.675662757996455 -0.594748263116706
## ... ... ...
## Ziggs -0.428154895446111 -0.235026925120569 -0.570092537129145
## Zilean -0.379852255572269 -0.58679345836942 -0.702042141038111
## Zoe -0.963730319981353 -0.705898175100211 -0.578978939025055
## Zyra -0.5284757628764 -0.149426957586878 -0.881116603485993
## champion_final_magicResist
## Aatrox 0.516079264044892
## Ahri -0.757380662470859
## Akali 0.1307196348019
## Akshan -0.504563789524599
## ...
## Ziggs -0.788295769217005
## Zilean -0.684100409442957
## Zoe -0.836156934475853
## Zyra -0.817149868846741
Principal Component Analysis (PCA) is used to identify correlations among variables and to group them by reducing dimensionality while preserving as much variance as possible.
res_pca1 <- PCA(analysis_df, graph = FALSE)
Visualization of the explained variance by each principal component:
fviz_eig(res_pca1, addlabels = TRUE)
Visualization of the individuals in the first two principal components:
fviz_pca_ind(res_pca1, col.ind = "cos2", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))
Visualization of the variables in the first two principal components:
fviz_pca_var(res_pca1, col.var = "contrib", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))
Visualization of the contribution of variables to the first two principal components:
pc1_1 <- fviz_contrib(res_pca1, choice = "var", axes = 1)
pc2_1 <- fviz_contrib(res_pca1, choice = "var", axes = 2)
grid.arrange(pc1_1, pc2_1, nrow = 1)
It is evident that the number of variables is overwhelming, and the principal components do not explain much variability. The best approach is to reduce the dimensionality and the number of variables.
The dummy variables resulting from the categorical variable “resource” contribute virtually nothing to the explainability of the first two principal components. They will be eliminated to begin reducing dimensionality.
resource_dummy <- c("resourceBlood.Well", "resourceCourage", "resourceCrimson.Rush", "resourceEnergy",
"resourceFerocity", "resourceFlow", "resourceFrenzy", "resourceFury",
"resourceGrit", "resourceHealth", "resourceHeat", "resourceMana",
"resourceNone", "resourceRage", "resourceShield")
del_vars1 <- resource_dummy
reduced1_df <- analysis_df[, !names(analysis_df) %in% del_vars1]
show_df(reduced1_df)
## rangetypeMelee rangetypeRanged adaptivetypeMagic
## Aatrox 0.939338530740863 -0.939338530740863 -0.928174518346596
## Ahri -1.05824214222705 1.05824214222705 1.07097059809223
## Akali 0.939338530740863 -0.939338530740863 -0.928174518346596
## Akshan -1.05824214222705 1.05824214222705 -0.928174518346596
## ... ... ...
## Ziggs -1.05824214222705 1.05824214222705 1.07097059809223
## Zilean -1.05824214222705 1.05824214222705 1.07097059809223
## Zoe -1.05824214222705 1.05824214222705 1.07097059809223
## Zyra -1.05824214222705 1.05824214222705 1.07097059809223
## adaptivetypePhysical champion_damage champion_toughness
## Aatrox 0.928174518346596 0.774385424703707 1.83065336934879
## Ahri -1.07097059809223 0.774385424703707 -0.809258785591955
## Akali 0.928174518346596 0.774385424703707 -0.809258785591955
## Akshan 0.928174518346596 0.774385424703707 -0.809258785591955
## ... ... ...
## Ziggs -1.07097059809223 0.774385424703707 -0.809258785591955
## Zilean -1.07097059809223 -0.655249205518522 -0.809258785591955
## Zoe -1.07097059809223 0.774385424703707 -0.809258785591955
## Zyra -1.07097059809223 0.774385424703707 -0.809258785591955
## champion_control champion_mobility champion_utility
## Aatrox 0.00824715553052613 0.250705079828437 0.795239217269529
## Ahri 0.00824715553052613 1.52702184986412 -0.689207321633591
## Akali -1.37727497359787 1.52702184986412 -0.689207321633591
## Akshan -1.37727497359787 1.52702184986412 0.795239217269529
## ... ... ...
## Ziggs 0.00824715553052613 0.250705079828437 -0.689207321633591
## Zilean 0.00824715553052613 0.250705079828437 2.27968575617265
## Zoe 0.00824715553052613 0.250705079828437 -0.689207321633591
## Zyra 1.39376928465892 -1.02561169020724 -0.689207321633591
## champion_kills champion_assists champion_time_ccing_others
## Aatrox -0.159026760321902 -0.810047803947257 -0.154802630760136
## Ahri -0.1232072593701 -0.244098592270786 -0.354415291838222
## Akali 1.55857150105353 -0.856426214987895 -1.34503038821721
## Akshan 1.16580000193199 -0.820383564122028 -1.33255848837055
## ... ... ...
## Ziggs 0.653837544101415 0.556939832070813 -0.289709182167312
## Zilean -1.75213557183893 2.02117252349667 -0.0944065104221308
## Zoe 1.21731823668224 0.442230358548972 0.659382087138045
## Zyra -0.741447980384434 1.07060210688553 1.53832382536758
## champion_vision_score champion_total_damage_dealt_to_champions
## Aatrox -0.694411818739119 0.526279172116685
## Ahri -0.453211183308094 0.110877810201137
## Akali -0.509627091782893 0.708153142717392
## Akshan -0.698735781349894 0.408753888360733
## ... ...
## Ziggs -0.325073345735362 2.57385232254126
## Zilean 2.05710975927531 -1.76188104497941
## Zoe -0.154107143300923 0.99921989802892
## Zyra 2.09964874329336 0.976150143413274
## champion_total_damage_taken champion_damage_dealt_to_objectives
## Aatrox 0.97613612220722 -0.617475713208985
## Ahri -0.724009521044824 -0.861899182900195
## Akali 0.0696858290972184 -0.888711954312996
## Akshan -0.698422949399065 -0.451534065728636
## ... ...
## Ziggs -0.690772197088214 -0.149970741796532
## Zilean -1.08888873796288 -1.22825306755781
## Zoe -1.04938733284464 -0.949993484290738
## Zyra -0.495894543887284 0.0506811064250639
## champion_damage_dealt_to_turrets champion_final_attackDamage
## Aatrox 0.290659851304982 1.31959872136325
## Ahri -0.282329555836636 -0.917679263156813
## Akali 0.0287674318798189 -0.73742948246733
## Akshan -0.259622084290543 0.870998900434925
## ... ...
## Ziggs 1.76666523576153 -0.862957173706503
## Zilean -1.13741244065152 -1.0218589448223
## Zoe -0.262946421256272 -0.845438148197303
## Zyra -0.888185554881257 -0.96360251803662
## champion_final_abilityPower champion_final_attackSpeed
## Aatrox -0.822765451694239 -0.607880404552245
## Ahri 1.39289953714227 -0.567013757225473
## Akali 1.54129605505782 -0.266891693705877
## Akshan -0.815353784811066 1.12574973470565
## ... ...
## Ziggs 2.16280364100328 -0.78462599711132
## Zilean 0.0366065615195856 -0.875006033085359
## Zoe 1.54241055083768 -0.525606826958317
## Zyra 0.703412391380462 -0.886995221530895
## champion_final_ccReduction champion_final_healthMax champion_final_armor
## Aatrox 1.98675853426468 0.598155111811785 0.0216848040995538
## Ahri -0.511186905904286 -0.819171601525684 -0.601137239856415
## Akali 0.0442963691187498 0.112088327841134 -0.169168740636517
## Akshan 1.07487463392056 -0.675662757996455 -0.594748263116706
## ... ... ...
## Ziggs -0.428154895446111 -0.235026925120569 -0.570092537129145
## Zilean -0.379852255572269 -0.58679345836942 -0.702042141038111
## Zoe -0.963730319981353 -0.705898175100211 -0.578978939025055
## Zyra -0.5284757628764 -0.149426957586878 -0.881116603485993
## champion_final_magicResist
## Aatrox 0.516079264044892
## Ahri -0.757380662470859
## Akali 0.1307196348019
## Akshan -0.504563789524599
## ...
## Ziggs -0.788295769217005
## Zilean -0.684100409442957
## Zoe -0.836156934475853
## Zyra -0.817149868846741
To verify the results and continue reducing dimensionality, the PCA will be repeated with the new dataframe.
res_pca2 <- PCA(reduced1_df, graph = FALSE)
Visualization of the explained variance by each principal component:
fviz_eig(res_pca2, addlabels = TRUE)
Visualization of the individuals in the first two principal components:
fviz_pca_ind(res_pca2, col.ind = "cos2", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))
Visualization of the variables in the first two principal components:
fviz_pca_var(res_pca2, col.var = "contrib", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))
Visualization of the contribution of variables to the first two principal components:
pc1_2 <- fviz_contrib(res_pca2, choice = "var", axes = 1)
pc2_2 <- fviz_contrib(res_pca2, choice = "var", axes = 2)
grid.arrange(pc1_2, pc2_2, nrow = 1)
The number of variables is still too high to be able to perform clustering and adequately interpret the profiles that make up each one.
To reduce dimensionality, the correlation between variables will be calculated first.
cor_matrix <- cor(reduced1_df)
Visualization of the correlation matrix:
corrplot(cor_matrix, method = "color", col = colorRampPalette(c("blue", "white", "red"))(200),
type = "upper", order = "hclust", tl.col = "black", tl.cex = 0.5, diag = FALSE)
Positively correlated variables are grouped together, those with a correlation greater than 0.5. Only positive correlations are sought, because it might be interesting to retain negative correlations to describe clusters.
cor_long <- melt(cor_matrix)
cor_long <- cor_long %>%
filter(as.character(Var1) != as.character(Var2)) %>%
filter(value > 0.5)
groups <- list()
used <- c()
for (i in 1:nrow(cor_long)) {
var1 <- as.character(cor_long$Var1[i])
var2 <- as.character(cor_long$Var2[i])
if (!(var1 %in% used) && !(var2 %in% used)) {
groups[[length(groups) + 1]] <- unique(c(var1, var2))
used <- c(used, var1, var2)
}
else {
for (j in seq_along(groups)) {
if (var1 %in% groups[[j]] || var2 %in% groups[[j]]) {
groups[[j]] <- unique(c(groups[[j]], var1, var2))
used <- c(used, var1, var2)
break
}
}
}
}
for (i in seq_along(groups)) {
cat(paste0("Group ", i, ": ", paste(groups[[i]], collapse = ", "), "\n"))
}
## Group 1: champion_toughness, rangetypeMelee, champion_total_damage_taken, champion_final_magicResist, champion_final_healthMax, champion_final_armor, champion_damage_dealt_to_objectives, champion_final_ccReduction
## Group 2: champion_final_abilityPower, adaptivetypeMagic
## Group 3: champion_final_attackDamage, adaptivetypePhysical, champion_kills, champion_total_damage_dealt_to_champions, champion_damage_dealt_to_turrets
## Group 4: champion_kills, champion_damage, champion_total_damage_dealt_to_champions
## Group 5: champion_time_ccing_others, champion_control
## Group 6: champion_vision_score, champion_assists
Some variables are chosen as representatives of each group, the other variables are eliminated from the dataframe. This selection was made based on the contribution of the variables to the first two principal components.
# Group 1: champion_final_magicResist, champion_final_armor, champion_final_healthMax
del_vg1 <- c("champion_toughness", "rangetypeMelee", "champion_total_damage_taken",
"champion_damage_dealt_to_objectives", "champion_final_ccReduction")
# Group 2: champion_final_abilityPower, adaptivetypeMagic
del_vg2 <- c()
# Group 3: champion_final_attackDamage, adaptivetypePhysical
del_vg3 <- c("champion_total_damage_dealt_to_champions", "champion_damage_dealt_to_turrets")
# Group 4: champion_kills
del_vg4 <- c("champion_damage", "champion_total_damage_dealt_to_champions")
# Group 5: champion_control
del_vg5 <- c("champion_time_ccing_others")
# Group 6: champion_assists, champion_vision_score
del_vg6 <- c()
del_vars2 <- Reduce(union, list(del_vg1, del_vg2, del_vg3, del_vg4, del_vg5, del_vg6))
reduced2_df <- reduced1_df[, !names(reduced1_df) %in% del_vars2]
show_df(reduced2_df)
## rangetypeRanged adaptivetypeMagic adaptivetypePhysical
## Aatrox -0.939338530740863 -0.928174518346596 0.928174518346596
## Ahri 1.05824214222705 1.07097059809223 -1.07097059809223
## Akali -0.939338530740863 -0.928174518346596 0.928174518346596
## Akshan 1.05824214222705 -0.928174518346596 0.928174518346596
## ... ... ...
## Ziggs 1.05824214222705 1.07097059809223 -1.07097059809223
## Zilean 1.05824214222705 1.07097059809223 -1.07097059809223
## Zoe 1.05824214222705 1.07097059809223 -1.07097059809223
## Zyra 1.05824214222705 1.07097059809223 -1.07097059809223
## champion_control champion_mobility champion_utility
## Aatrox 0.00824715553052613 0.250705079828437 0.795239217269529
## Ahri 0.00824715553052613 1.52702184986412 -0.689207321633591
## Akali -1.37727497359787 1.52702184986412 -0.689207321633591
## Akshan -1.37727497359787 1.52702184986412 0.795239217269529
## ... ... ...
## Ziggs 0.00824715553052613 0.250705079828437 -0.689207321633591
## Zilean 0.00824715553052613 0.250705079828437 2.27968575617265
## Zoe 0.00824715553052613 0.250705079828437 -0.689207321633591
## Zyra 1.39376928465892 -1.02561169020724 -0.689207321633591
## champion_kills champion_assists champion_vision_score
## Aatrox -0.159026760321902 -0.810047803947257 -0.694411818739119
## Ahri -0.1232072593701 -0.244098592270786 -0.453211183308094
## Akali 1.55857150105353 -0.856426214987895 -0.509627091782893
## Akshan 1.16580000193199 -0.820383564122028 -0.698735781349894
## ... ... ...
## Ziggs 0.653837544101415 0.556939832070813 -0.325073345735362
## Zilean -1.75213557183893 2.02117252349667 2.05710975927531
## Zoe 1.21731823668224 0.442230358548972 -0.154107143300923
## Zyra -0.741447980384434 1.07060210688553 2.09964874329336
## champion_final_attackDamage champion_final_abilityPower
## Aatrox 1.31959872136325 -0.822765451694239
## Ahri -0.917679263156813 1.39289953714227
## Akali -0.73742948246733 1.54129605505782
## Akshan 0.870998900434925 -0.815353784811066
## ... ...
## Ziggs -0.862957173706503 2.16280364100328
## Zilean -1.0218589448223 0.0366065615195856
## Zoe -0.845438148197303 1.54241055083768
## Zyra -0.96360251803662 0.703412391380462
## champion_final_attackSpeed champion_final_healthMax champion_final_armor
## Aatrox -0.607880404552245 0.598155111811785 0.0216848040995538
## Ahri -0.567013757225473 -0.819171601525684 -0.601137239856415
## Akali -0.266891693705877 0.112088327841134 -0.169168740636517
## Akshan 1.12574973470565 -0.675662757996455 -0.594748263116706
## ... ... ...
## Ziggs -0.78462599711132 -0.235026925120569 -0.570092537129145
## Zilean -0.875006033085359 -0.58679345836942 -0.702042141038111
## Zoe -0.525606826958317 -0.705898175100211 -0.578978939025055
## Zyra -0.886995221530895 -0.149426957586878 -0.881116603485993
## champion_final_magicResist
## Aatrox 0.516079264044892
## Ahri -0.757380662470859
## Akali 0.1307196348019
## Akshan -0.504563789524599
## ...
## Ziggs -0.788295769217005
## Zilean -0.684100409442957
## Zoe -0.836156934475853
## Zyra -0.817149868846741
A final PCA is performed to check the new distribution of individuals and variables.
res_pca3 <- PCA(reduced2_df, graph = FALSE)
Visualization of the explained variance by each principal component:
fviz_eig(res_pca3, addlabels = TRUE)
Visualization of the individuals in the first two principal components:
fviz_pca_ind(res_pca3, col.ind = "cos2", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))
Visualization of the variables in the first two principal components:
fviz_pca_var(res_pca3, col.var = "contrib", gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))
Visualization of the contribution of variables to the frist two principal components:
pc1_3 <- fviz_contrib(res_pca3, choice = "var", axes = 1)
pc2_3 <- fviz_contrib(res_pca3, choice = "var", axes = 2)
grid.arrange(pc1_3, pc2_3, nrow = 1)
The dimensionality of the dataframe is now more suitable for clustering.
A clustering will be performed to group the champions of the video game. This is the new dataframe prepared for the clustering.
clust_df <- reduced2_df
show_df(clust_df)
## rangetypeRanged adaptivetypeMagic adaptivetypePhysical
## Aatrox -0.939338530740863 -0.928174518346596 0.928174518346596
## Ahri 1.05824214222705 1.07097059809223 -1.07097059809223
## Akali -0.939338530740863 -0.928174518346596 0.928174518346596
## Akshan 1.05824214222705 -0.928174518346596 0.928174518346596
## ... ... ...
## Ziggs 1.05824214222705 1.07097059809223 -1.07097059809223
## Zilean 1.05824214222705 1.07097059809223 -1.07097059809223
## Zoe 1.05824214222705 1.07097059809223 -1.07097059809223
## Zyra 1.05824214222705 1.07097059809223 -1.07097059809223
## champion_control champion_mobility champion_utility
## Aatrox 0.00824715553052613 0.250705079828437 0.795239217269529
## Ahri 0.00824715553052613 1.52702184986412 -0.689207321633591
## Akali -1.37727497359787 1.52702184986412 -0.689207321633591
## Akshan -1.37727497359787 1.52702184986412 0.795239217269529
## ... ... ...
## Ziggs 0.00824715553052613 0.250705079828437 -0.689207321633591
## Zilean 0.00824715553052613 0.250705079828437 2.27968575617265
## Zoe 0.00824715553052613 0.250705079828437 -0.689207321633591
## Zyra 1.39376928465892 -1.02561169020724 -0.689207321633591
## champion_kills champion_assists champion_vision_score
## Aatrox -0.159026760321902 -0.810047803947257 -0.694411818739119
## Ahri -0.1232072593701 -0.244098592270786 -0.453211183308094
## Akali 1.55857150105353 -0.856426214987895 -0.509627091782893
## Akshan 1.16580000193199 -0.820383564122028 -0.698735781349894
## ... ... ...
## Ziggs 0.653837544101415 0.556939832070813 -0.325073345735362
## Zilean -1.75213557183893 2.02117252349667 2.05710975927531
## Zoe 1.21731823668224 0.442230358548972 -0.154107143300923
## Zyra -0.741447980384434 1.07060210688553 2.09964874329336
## champion_final_attackDamage champion_final_abilityPower
## Aatrox 1.31959872136325 -0.822765451694239
## Ahri -0.917679263156813 1.39289953714227
## Akali -0.73742948246733 1.54129605505782
## Akshan 0.870998900434925 -0.815353784811066
## ... ...
## Ziggs -0.862957173706503 2.16280364100328
## Zilean -1.0218589448223 0.0366065615195856
## Zoe -0.845438148197303 1.54241055083768
## Zyra -0.96360251803662 0.703412391380462
## champion_final_attackSpeed champion_final_healthMax champion_final_armor
## Aatrox -0.607880404552245 0.598155111811785 0.0216848040995538
## Ahri -0.567013757225473 -0.819171601525684 -0.601137239856415
## Akali -0.266891693705877 0.112088327841134 -0.169168740636517
## Akshan 1.12574973470565 -0.675662757996455 -0.594748263116706
## ... ... ...
## Ziggs -0.78462599711132 -0.235026925120569 -0.570092537129145
## Zilean -0.875006033085359 -0.58679345836942 -0.702042141038111
## Zoe -0.525606826958317 -0.705898175100211 -0.578978939025055
## Zyra -0.886995221530895 -0.149426957586878 -0.881116603485993
## champion_final_magicResist
## Aatrox 0.516079264044892
## Ahri -0.757380662470859
## Akali 0.1307196348019
## Akshan -0.504563789524599
## ...
## Ziggs -0.788295769217005
## Zilean -0.684100409442957
## Zoe -0.836156934475853
## Zyra -0.817149868846741
To determine the optimal number of clusters, the Silhouette coefficient analysis will be used along with intra-cluster variability.
oc1 <- fviz_nbclust(x = clust_df, FUNcluster = kmeans, method = "silhouette", k.max = 8, verbose = FALSE)
oc2 <- fviz_nbclust(x = clust_df, FUNcluster = kmeans, method = "wss", k.max = 8, verbose = FALSE)
grid.arrange(oc1, oc2, nrow = 1)
Considering both analyses, and following the elbow method, it can be seen that the optimal number of clusters is 4. For 4 clusters, the Silhouette coefficient remains almost at the same level and the intra-cluster variability is much lower.
A partition-based clustering using K-means will be performed to group the champions with the most similar values in their variables.
set.seed(123)
k <- 4
kmeans_result <- kmeans(clust_df, centers = k, nstart = 25)
The validity of the clustering will be evaluated using the Silhouette method.
sil <- silhouette(kmeans_result$cluster, dist(clust_df))
fviz_silhouette(sil)
## cluster size ave.sil.width
## 1 1 78 0.31
## 2 2 46 0.35
## 3 3 20 0.14
## 4 4 24 0.29
Most individuals are well positioned, therefore it is assumed that the clustering partition is valid.
To describe each cluster based on its values on the variables, a table of means will be created.
clust_means <- clust_df %>%
mutate(cluster = kmeans_result$cluster) %>%
group_by(cluster) %>%
summarise_all(mean)
Visualization of the table of means using a bar chart:
clust_means_long <- clust_means %>%
pivot_longer(-cluster, names_to = "variable", values_to = "mean_value")
ggplot(clust_means_long, aes(x = factor(cluster), y = mean_value, fill = variable)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Mean Values of Each Variable by Cluster", x = "Cluster", y = "Mean Value") +
theme_minimal()
Each cluster has high values in the following variables.
Cluster 1: “adaptivetypePhysical”, “champion_final_attackDamage”, “champion_final_attackSpeed”, “champion_kills” and “champion_mobility”.
Cluster 2: “adaptivetypeMagic”, “champion_final_abilityPower”, “champion_kills” and “rangetypeRanged”.
Cluster 3: “champion_assists”, “champion_control”, “champion_final_armor”, “champion_final_healthMax” and “champion_final_magicResist”.
Cluster 4: “adaptivetypeMagic”, “champion_assists”, “champion_control”, “champion_utility”, “champion_vision_score” and “rangetypeRanged”.
In order to describe the profile that makes up each cluster we will use the following dataframe.
champion_names <- champion_stats_df[, "champion_name"]
champion_names <- data.frame("champion_name" = champion_names)
champion_names <- unique(champion_names)
champion_names <- champion_names[order(champion_names[, "champion_name"]), ]
profiles_df <- data.frame("champion_name" = champion_names)
profiles_df$champion_gold_earned <- prepared_df$champion_gold_earned
profiles_df$cluster <- as.factor(kmeans_result$cluster)
show(profiles_df)
## champion_name champion_gold_earned cluster
## 1 Aatrox 0.004740539 1
## 2 Ahri -0.067190352 2
## 3 Akali 0.729816544 1
## 4 Akshan 0.373873061 1
## 5 Alistar -2.750348086 4
## 6 Ambessa 0.027470936 1
## 7 Amumu 0.003317242 3
## 8 Anivia -0.529453552 2
## 9 Annie 0.519648464 2
## 10 Aphelios 0.387209213 1
## 11 Ashe -0.026625019 1
## 12 AurelionSol 0.681578454 2
## 13 Aurora -0.003422328 2
## 14 Azir 0.029797164 2
## 15 Bard -2.219889362 4
## 16 Belveth 0.864401185 1
## 17 Blitzcrank -1.840079470 4
## 18 Brand 0.296414765 2
## 19 Braum -2.128448998 4
## 20 Briar 0.086600752 1
## 21 Caitlyn 0.912762032 1
## 22 Camille 0.200990022 1
## 23 Cassiopeia 0.154276633 2
## 24 Chogath 0.124448505 3
## 25 Corki 0.591042341 1
## 26 Darius 0.470880276 1
## 27 Diana 0.628437082 2
## 28 Draven 0.271122322 3
## 29 DrMundo 1.736616542 1
## 30 Ekko -0.214823242 2
## 31 Elise -0.055030106 2
## 32 Evelynn 0.448833126 2
## 33 Ezreal 0.861813097 1
## 34 Fiora 0.384066958 1
## 35 Fizz 1.322647461 2
## 36 Galio -1.180688772 3
## 37 Gangplank 0.472019490 1
## 38 Garen 0.947548303 1
## 39 Gnar -0.323272446 1
## 40 Gragas -0.295837473 2
## 41 Graves 1.846973624 1
## 42 Gwen -0.012420782 2
## 43 Hecarim 0.233045625 1
## 44 Heimerdinger 1.460857609 2
## 45 Hwei -0.067880934 2
## 46 Illaoi 0.686813191 1
## 47 Irelia 1.222205926 1
## 48 Ivern -0.284750294 4
## 49 Janna -1.996176362 4
## 50 JarvanIV -0.131967301 1
## 51 Jax 0.179493823 1
## 52 Jayce 0.480884650 1
## 53 Jhin 1.121096828 1
## 54 Jinx 0.612214563 1
## 55 Kaisa -1.161974218 3
## 56 Kalista 0.947806493 1
## 57 Karma 0.004553208 1
## 58 Karthus -1.597334741 4
## 59 Kassadin 1.733919539 2
## 60 Katarina 0.175230595 2
## 61 Kayle 0.550369825 1
## 62 Kayn 0.223286076 1
## 63 Kennen 0.756664702 1
## 64 Khazix -0.022691988 2
## 65 Kindred 1.353694519 1
## 66 Kled 0.774421739 1
## 67 KogMaw -1.443932039 1
## 68 KSante 0.706868768 1
## 69 Leblanc 0.073124972 2
## 70 LeeSin 0.267043746 1
## 71 Leona -1.731842593 3
## 72 Lillia 0.329286279 2
## 73 Lissandra 0.610814274 2
## 74 Lucian 0.995885516 1
## 75 Lulu -1.973322462 4
## 76 Lux -0.377065908 2
## 77 Malphite -0.271346689 3
## 78 Malzahar 0.805850742 2
## 79 Maokai -0.835891876 3
## 80 MasterYi 0.640021253 1
## 81 Milio -2.204745506 4
## 82 MissFortune 1.399966686 1
## 83 MonkeyKing 0.123443776 1
## 84 Mordekaiser 0.373425660 2
## 85 Morgana -0.915676832 4
## 86 Naafiri -0.395499690 1
## 87 Nami -2.089401974 4
## 88 Nasus 0.132972707 3
## 89 Nautilus -1.677503136 4
## 90 Neeko -1.739195704 2
## 91 Nidalee 0.898633099 2
## 92 Nilah 0.380385224 1
## 93 Nocturne 0.507009647 1
## 94 Nunu -0.258827631 3
## 95 Olaf 2.264210907 1
## 96 Orianna 0.854225929 2
## 97 Ornn -0.809748100 3
## 98 Pantheon 0.069264286 1
## 99 Poppy -1.365045139 3
## 100 Pyke -1.089398763 1
## 101 Qiyana -0.235147863 1
## 102 Quinn 1.849433292 1
## 103 Rakan -1.979099198 4
## 104 Rammus -0.474218914 3
## 105 RekSai 0.239757834 1
## 106 Rell -1.905952531 4
## 107 Renata -1.769303514 4
## 108 Renekton 0.921434872 1
## 109 Rengar 0.395599460 1
## 110 Riven 0.685801910 1
## 111 Rumble 0.752162673 2
## 112 Ryze 0.519688956 2
## 113 Samira 0.926561902 1
## 114 Sejuani 0.805439441 3
## 115 Senna -0.878605512 4
## 116 Seraphine -1.368009517 4
## 117 Sett 0.773841155 1
## 118 Shaco 0.194427771 1
## 119 Shen -0.467397436 3
## 120 Shyvana -0.468712711 1
## 121 Singed 0.132274680 2
## 122 Sion 0.761336347 3
## 123 Sivir 0.637736769 1
## 124 Skarner -1.048027144 3
## 125 Smolder 0.530461640 1
## 126 Sona -1.450912316 4
## 127 Soraka -2.454098445 4
## 128 Swain -0.025459914 2
## 129 Sylas 0.052935754 2
## 130 Syndra 0.273274372 2
## 131 TahmKench -0.824841496 3
## 132 Taliyah 0.538508186 2
## 133 Talon 0.478342403 1
## 134 Taric -2.126839303 4
## 135 Teemo -0.157261844 2
## 136 Thresh -2.046136318 4
## 137 Tristana 1.334042331 1
## 138 Trundle 0.685527767 1
## 139 Tryndamere 0.912947254 1
## 140 TwistedFate -0.841546522 2
## 141 Twitch 0.902205268 1
## 142 Udyr -1.144629341 1
## 143 Urgot 0.667121056 1
## 144 Varus 0.830862618 1
## 145 Vayne 1.136515642 1
## 146 Veigar 0.595980640 2
## 147 Velkoz -1.037017394 2
## 148 Vex -0.141440079 2
## 149 Vi 0.168342208 1
## 150 Viego 0.725725042 1
## 151 Viktor 0.299136696 2
## 152 Vladimir 0.044244474 2
## 153 Volibear 0.636138412 3
## 154 Warwick 0.272457803 1
## 155 Xayah 0.536054992 1
## 156 Xerath -0.792753309 2
## 157 XinZhao -0.374529806 1
## 158 Yasuo 0.346501210 1
## 159 Yone 0.362310803 1
## 160 Yorick 0.476924326 1
## 161 Yuumi -2.171084050 4
## 162 Zac 0.020414180 3
## 163 Zed 0.907808108 1
## 164 Zeri -0.235924600 1
## 165 Ziggs 1.652051448 2
## 166 Zilean -1.769177757 4
## 167 Zoe 0.260036837 2
## 168 Zyra -0.293830351 4
The “champion_gold_earned” by each champion will be used as a measure of success and performance in matches.
Fast attackers with high physical damage, without many defenses but great mobility. Ideal for finishing off your enemies with a flurry of attacks.
Champions ordered by their gold earnings:
cbest_df <- profiles_df[profiles_df$cluster == "1", ]
cbest_df <- cbest_df[order(cbest_df$champion_gold_earned), ]
cbest_names <- cbest_df[, c("champion_name", "champion_gold_earned")]
cbest_names
ggplot(cbest_df, aes(x = reorder(cbest_df$champion_name, cbest_df$champion_gold_earned),
y = cbest_df$champion_gold_earned)) +
geom_bar(stat = "identity", fill = "gold") +
labs(title = "Gold Earned by Champions", x = "Champion", y = "Gold") +
theme_minimal()
## Warning: Use of `cbest_df$champion_name` is discouraged.
## ℹ Use `champion_name` instead.
## Warning: Use of `cbest_df$champion_gold_earned` is discouraged.
## ℹ Use `champion_gold_earned` instead.
## Use of `cbest_df$champion_gold_earned` is discouraged.
## ℹ Use `champion_gold_earned` instead.
Mages with huge magic damage and some opponent control, with low mobility, health and defenses. Their fragility is compensated by their ability to eliminate their opponents with a few high-damage attacks.
Champions ordered by their gold earnings:
cbest_df <- profiles_df[profiles_df$cluster == "2", ]
cbest_df <- cbest_df[order(cbest_df$champion_gold_earned), ]
cbest_names <- cbest_df[, c("champion_name", "champion_gold_earned")]
cbest_names
ggplot(cbest_df, aes(x = reorder(cbest_df$champion_name, cbest_df$champion_gold_earned),
y = cbest_df$champion_gold_earned)) +
geom_bar(stat = "identity", fill = "gold") +
labs(title = "Gold Earned by Champions", x = "Champion", y = "Gold") +
theme_minimal()
## Warning: Use of `cbest_df$champion_name` is discouraged.
## ℹ Use `champion_name` instead.
## Warning: Use of `cbest_df$champion_gold_earned` is discouraged.
## ℹ Use `champion_gold_earned` instead.
## Use of `cbest_df$champion_gold_earned` is discouraged.
## ℹ Use `champion_gold_earned` instead.
Champions with little attack capacity and speed, however, great resistance and defenses with gigantic amounts of life. They are those who position themselves at the front of the team to resist all of the rival’s attacks and ensure that their teammates are protected.
Champions ordered by their gold earnings:
cbest_df <- profiles_df[profiles_df$cluster == "3", ]
cbest_df <- cbest_df[order(cbest_df$champion_gold_earned), ]
cbest_names <- cbest_df[, c("champion_name", "champion_gold_earned")]
cbest_names
ggplot(cbest_df, aes(x = reorder(cbest_df$champion_name, cbest_df$champion_gold_earned),
y = cbest_df$champion_gold_earned)) +
geom_bar(stat = "identity", fill = "gold") +
labs(title = "Gold Earned by Champions", x = "Champion", y = "Gold") +
theme_minimal()
## Warning: Use of `cbest_df$champion_name` is discouraged.
## ℹ Use `champion_name` instead.
## Warning: Use of `cbest_df$champion_gold_earned` is discouraged.
## ℹ Use `champion_gold_earned` instead.
## Use of `cbest_df$champion_gold_earned` is discouraged.
## ℹ Use `champion_gold_earned` instead.
Champions whose attack and defense capacity is low, but their usefulness towards the rest of the team is excellent, providing vision of the map and remarkable control of opponents. They are responsible for complementing their teammates and covering their weaknesses, making them essential to complete the team.
Champions ordered by their gold earnings:
cbest_df <- profiles_df[profiles_df$cluster == "4", ]
cbest_df <- cbest_df[order(cbest_df$champion_gold_earned), ]
cbest_names <- cbest_df[, c("champion_name", "champion_gold_earned")]
cbest_names
ggplot(cbest_df, aes(x = reorder(cbest_df$champion_name, cbest_df$champion_gold_earned),
y = cbest_df$champion_gold_earned)) +
geom_bar(stat = "identity", fill = "gold") +
labs(title = "Gold Earned by Champions", x = "Champion", y = "Gold") +
theme_minimal()
## Warning: Use of `cbest_df$champion_name` is discouraged.
## ℹ Use `champion_name` instead.
## Warning: Use of `cbest_df$champion_gold_earned` is discouraged.
## ℹ Use `champion_gold_earned` instead.
## Use of `cbest_df$champion_gold_earned` is discouraged.
## ℹ Use `champion_gold_earned` instead.