Data Mining PUBG

Madrugada

Team Liquid

20/12/2023

Objetivos

  • Criação de Indicadores com Base nas Métricas Consideradas
  • Redução da Complexidade de Problemas com Muitas Variáveis
  • Scout de Players com base nos Indicadores, Correlação e Clusterização

Tratamento dos Dados

Importando Bibliotecas

Show
rm(list=ls())
library(dplyr)
require(ggplot2)
require(plotly)
require(heatmaply)
require(factoextra)

Carregando e Pré-Visualizando os Dados

        MODALIDADE   ID       Jogador Abates Assistencias Cura Dano
1 PMNC_SPLIT1_2023 D1Q1   BSgaaralove      5            0   61  480
2 PMNC_SPLIT1_2023 D1Q1  KSzoppiiiiii      4            3  160  795
3 PMNC_SPLIT1_2023 D1Q1 SMKCARDOSOOOO      3            2  317  462
  Granada.Fumaça Headshots Abates.por.granada Knockouts Tempo.sobrevivencia
1              1         0                  3         4                1594
2             10         1                  0         4                1561
3             10         0                  0         3                1491
  Dano_1 INTENSIDADE_DE_COMBATE DMG_P_CURA PART_EFET              MATCH_ID Dia
1    480             0.29123268   7.741935  462.2600 PMNC_SPLIT1_2023_D1Q1   1
2    795             0.18967560   4.937888  571.7162 PMNC_SPLIT1_2023_D1Q1   1
3    462             0.05842481   1.452830  374.2410 PMNC_SPLIT1_2023_D1Q1   1
  Queda
1     1
2     1
3     1

'data.frame':   8820 obs. of  19 variables:
 $ MODALIDADE            : chr  "PMNC_SPLIT1_2023" "PMNC_SPLIT1_2023" "PMNC_SPLIT1_2023" "PMNC_SPLIT1_2023" ...
 $ ID                    : chr  "D1Q1" "D1Q1" "D1Q1" "D1Q1" ...
 $ Jogador               : chr  "BSgaaralove" "KSzoppiiiiii" "SMKCARDOSOOOO" "DMSGUIZAO" ...
 $ Abates                : int  5 4 3 3 3 3 3 2 2 2 ...
 $ Assistencias          : num  0 3 2 0 2 1 2 0 2 2 ...
 $ Cura                  : int  61 160 317 66 377 240 330 141 252 236 ...
 $ Dano                  : int  480 795 462 295 229 496 656 432 308 449 ...
 $ Granada.Fumaça        : int  1 10 10 1 6 4 5 5 3 4 ...
 $ Headshots             : int  0 1 0 1 0 1 0 0 0 0 ...
 $ Abates.por.granada    : int  3 0 0 0 1 1 0 1 1 1 ...
 $ Knockouts             : int  4 4 3 1 0 3 3 3 2 2 ...
 $ Tempo.sobrevivencia   : int  1594 1561 1491 809 1487 1562 1340 1102 1592 1478 ...
 $ Dano_1                : int  480 795 462 295 229 496 656 432 308 449 ...
 $ INTENSIDADE_DE_COMBATE: num  0.2912 0.1897 0.0584 0.3261 0.0244 ...
 $ DMG_P_CURA            : num  7.742 4.938 1.453 4.403 0.606 ...
 $ PART_EFET             : num  462 572 374 124 251 ...
 $ MATCH_ID              : chr  "PMNC_SPLIT1_2023_D1Q1" "PMNC_SPLIT1_2023_D1Q1" "PMNC_SPLIT1_2023_D1Q1" "PMNC_SPLIT1_2023_D1Q1" ...
 $ Dia                   : int  1 1 1 1 1 1 1 1 1 1 ...
 $ Queda                 : int  1 1 1 1 1 1 1 1 1 1 ...

Filtrando dados por Modalidade

Show
dados =  dados[dados$MODALIDADE == "PMPL_FALL_2023",]

Verificando a quantidade de dados nulos e substituindo por 0

Show
sum(is.na(dados))
[1] 0
Show
data = mutate_all(dados, ~replace(., is.na(.), 0))
sum(is.na(data))
[1] 0

Em uma análise de componentes principais é comum usarmos apenas variáveis quantitativas, assim filtraremos apenas esse tipo de variável.

Show
sel = c()
for(i in 1:ncol(data)){
  if(class(data[,i]) == 'numeric' | class(data[,i]) == 'integer'){
    sel = append(sel,i)
  }
}
data = data[,sel]
colnames(data)
 [1] "Abates"                 "Assistencias"           "Cura"                  
 [4] "Dano"                   "Granada.Fumaça"         "Headshots"             
 [7] "Abates.por.granada"     "Knockouts"              "Tempo.sobrevivencia"   
[10] "Dano_1"                 "INTENSIDADE_DE_COMBATE" "DMG_P_CURA"            
[13] "PART_EFET"              "Dia"                    "Queda"                 

Removendo variáveis que tem variabilidade igual zero, ou seja, que todas as métricas são iguais

Show
X = data
round(sapply(X, var),1)
                Abates           Assistencias                   Cura 
                   1.7                    1.1                15664.5 
                  Dano         Granada.Fumaça              Headshots 
               44436.8                    5.3                    0.1 
    Abates.por.granada              Knockouts    Tempo.sobrevivencia 
                   0.1                    1.5               125593.4 
                Dano_1 INTENSIDADE_DE_COMBATE             DMG_P_CURA 
               44436.8                  535.7                 3105.2 
             PART_EFET                    Dia                  Queda 
               17538.8                   37.9                    2.2 
Show
X = X[,sapply(X, var) != 0]
sel = c()
for(i in 1:ncol(X)){
  if(dim(table(X[,i] < 0)) == 2){
    sel = append(sel,i)
  }
}
if(length(sel) > 0){
  X = X[,-sel]
} else{
  
}
NULL

Excluindo variáveis que restaram e qua não fazem sentido fazer parte da ACP

Show
excluir = c("Queda","Dia","Dano_1")
X <- X[, setdiff(names(X), excluir)]

Criando Categorias

Separando métricas por categorias

Show
{

report = c("Abates"     ,            "Assistencias"    ,       "Cura"  ,                 "Dano"           ,        "Granada.Fumaça"  ,      
  "Headshots"       ,       "Abates.por.granada" ,    "Knockouts"   ,           "Tempo.sobrevivencia"   , "INTENSIDADE_DE_COMBATE",
 "DMG_P_CURA" ,            "PART_EFET")

report2 = c("Abates"     ,            "Assistencias"    ,       "Cura"  ,                 "Dano"           ,        "Granada.Fumaça"  ,      
  "Headshots"       ,       "Abates.por.granada" ,    "Knockouts"   ,           "Tempo.sobrevivencia"   , "INTENSIDADE_DE_COMBATE",
 "DMG_P_CURA" )
}

Análise de Componentes Principais

Aplicação

Selecionando as categorias para aplicação da técnica PCA

Show
#X1 = scale(X[,c(coletivo,individual,recursos,estrategia,vs,objetivos)],center = T,scale = T)
X1 = X[,c(report2)]
acpcor <- princomp(X1, cor= T)
screeplot(acpcor, type = c("lines"))

Componentes

Visualizando os Componentes

Show
mat = (acpcor$loadings[,1:5])

p <- heatmaply(round(mat,2), 
        dendrogram = "none",
        xlab = "", ylab = "", 
        main = "",
        scale = "column",
        margins = c(60,100,40,20),
        grid_color = "white",
        grid_width = 0.00001,
        titleX = FALSE,
        hide_colorbar = TRUE,
        branches_lwd = 0.1,
        #labCol = colnames(mat),
        #labRow = rownames(mat),
        heatmap_layers = theme(axis.line=element_blank()),
        col = colorRampPalette(c("#FFCC00","#FF9900",
                                 "#FF6600","#FF3300","#FF0000"))(100),
        na.rm = T,cellnote = round(mat,2)
        ,cellnote_size = 10,cellnote_textposition = "middle center")
p

Formação dos Scores

Atribuindo e Visualizando os Indicadores de Desempenho dos Jogadores

Show
dados$comp1 = acpcor$scores[,1]
dados$comp2 = acpcor$scores[,2]
dados$comp3 = acpcor$scores[,3]

dados[sample(1:nrow(dados),15),c('Jogador','comp1','comp2','comp3')]
           Jogador       comp1        comp2       comp3
4424      GZMBRO77  0.30403030 -1.225944917  0.10049009
2262    SMKRAGNAR7 -1.62011071 -0.372555529  0.63646746
5440       FLAfoox  0.07641995  0.660689443  0.29440087
4496  iNCOnenebete  1.84457822 -0.118363058 -0.36965651
6168     TSxCAPJAO -1.74936847  0.130646932  0.68606680
5502    A7REVOO77K  0.48833007 -0.582389708 -0.57869503
2045 LoopsMYTHIC44  1.16288604  1.512671166  1.36366364
4924    STGDADDYYY  2.03823805  0.720140749  0.19588206
6467  SCCPfoquisin  0.28696159  0.963287392  0.03177774
6831   SCCPp3dr0gg -0.70609984 -0.981211179 -0.62077539
8380  dcaGuiboy77K  2.72918538  0.080465605 -1.93012673
3133       DWHigor  1.52031081  1.134136768  0.93355452
4954        KSTHÅ« -1.88999400 -0.095717198  0.35535925
3350    SCCPren4nz -1.90234418 -0.004501379  0.28952251
3624 SoulsFake6666 -1.82996118  0.148125991  0.52605980

Visualização Prática - Ranking no Brasil por Componente

Componente 1

Show
avg_comp = dados |> group_by(Jogador) |> select(comp1,comp2,comp3) |> summarise_all(mean)
qtd_part = dados |> group_by(Jogador) |> summarise(qtd = n())

players = merge(avg_comp,qtd_part,by = c('Jogador'))

sel = players |> filter(qtd >= quantile(players$qtd,.5)) |> top_n(10,comp1) %>% select(Jogador,comp1) |> arrange(-comp1)

ggplot(data = sel, mapping = aes(x = reorder(Jogador,+comp1), y = comp1, fill = Jogador))+
  labs(title = "comp1")+
  xlab("")+ ylab("")+
  geom_bar(stat = "identity")+
  theme(legend.position = "none",panel.background = element_rect(fill = "#17202A"),plot.title = element_text(hjust = 0.5),axis.text.x = element_blank(), panel.grid = element_blank())+
  geom_text(aes(label = round(comp1,3)), vjust = 0.5,hjust = 1,color = "white")+
  coord_flip()

Componente 2

Show
sel = players |> filter(qtd >= quantile(players$qtd,.5)) |> top_n(10,comp2) %>% select(Jogador,comp2) |> arrange(-comp2)

ggplot(data = sel, mapping = aes(x = reorder(Jogador,+comp2), y = comp2, fill = Jogador))+
  labs(title = "comp2")+
  xlab("")+ ylab("")+
  geom_bar(stat = "identity")+
  theme(legend.position = "none",panel.background = element_rect(fill = "#17202A"),plot.title = element_text(hjust = 0.5),axis.text.x = element_blank(), panel.grid = element_blank())+
  geom_text(aes(label = round(comp2,3)), vjust = 0.5,hjust = 1,color = "white")+
  coord_flip()

Componente 3

Show
sel = players |> filter(qtd >= quantile(players$qtd,.5)) |> top_n(10,comp3) %>% select(Jogador,comp3) |> arrange(-comp3)

ggplot(data = sel, mapping = aes(x = reorder(Jogador,+comp3), y = comp3, fill = Jogador))+
  labs(title = "comp3")+
  xlab("")+ ylab("")+
  geom_bar(stat = "identity")+
  theme(legend.position = "none",panel.background = element_rect(fill = "#17202A"),plot.title = element_text(hjust = 0.5),axis.text.x = element_blank(), panel.grid = element_blank())+
  geom_text(aes(label = round(comp3,3)), vjust = 0.5,hjust = 1,color = "white")+
  coord_flip()

Clusterização

Selecionando e Criando Variáveis

Aplicando Técnica

Show
dt = dados
row.names(dt) = dt[,1]
dt = dt[,-1]
df <- scale(dt)
df.dist = dist(df, method = "euclidean")

df.hclust = hclust(df.dist, method = "ward.D2")
plot(df.hclust)

Perfumando o Visual

Show
p = fviz_dend(df.hclust, k = 15,
          
          cex = .7, 
          #k_colors = c("#2E9FDF", "#c066c0", "#E7B800", "#FC4E07"),
          color_labels_by_k = TRUE, 
          rect = TRUE,
          #rect_border = c("#2E9FDF", "#cc84cc", "#E7B800", "#FC4E07"),
          rect_fill = TRUE,
          #horiz = T,
          main = "",
          type = "rectangle"
          ,ylab = "",horiz = T
          )
p

Resumo das Métricas por Cluster

Show
groups.2 = cutree(df.hclust,15)
dados <- cbind(dados, clusterg2 = groups.2)

mat = dados %>% select(-Jogador) %>%
  group_by(clusterg2) %>%
  summarize_all(mean) %>% select(-clusterg2)


mat = mat %>% mutate_all(~ replace(., is.nan(.), NA))


mat = mat[,which(!(is.na(sapply(mat, sd)) | sapply(mat, sd) == 0))]

#sort(sapply(mat, var),decreasing = F)

mat = round(mat[,-which(colnames(mat) %in% c('Headshots','Abates.por.granada'))],2)


p <- heatmaply(mat[,1:round(ncol(mat)/2,0)], 
        dendrogram = "none",
        xlab = "", ylab = "Clusters", 
        main = "",
        scale = "column",
        margins = c(60,100,40,20),
        grid_color = "white",
        grid_width = 0.00001,
        titleX = FALSE,
        hide_colorbar = TRUE,
        branches_lwd = 0.1,
        #labCol = colnames(mat),
        #labRow = rownames(mat),
        heatmap_layers = theme(axis.line=element_blank()),
        col = colorRampPalette(c("#FFCC00","#FF9900",
                                 "#FF6600","#FF3300","#FF0000"))(100),
        na.rm = T,cellnote = round(mat,2)
        ,cellnote_size = 10,cellnote_textposition = "middle center")
p

Show
p <- heatmaply(mat[,round(ncol(mat)/2,0):ncol(mat)], 
        dendrogram = "none",
        xlab = "", ylab = "Clusters", 
        main = "",
        scale = "column",
        margins = c(60,100,40,20),
        grid_color = "white",
        grid_width = 0.00001,
        titleX = FALSE,
        hide_colorbar = TRUE,
        branches_lwd = 0.1,
        #labCol = colnames(mat),
        #labRow = rownames(mat),
        heatmap_layers = theme(axis.line=element_blank()),
        col = colorRampPalette(c("#FFCC00","#FF9900",
                                 "#FF6600","#FF3300","#FF0000"))(100),
        na.rm = T,cellnote = round(mat,2)
        ,cellnote_size = 10,cellnote_textposition = "middle center")
p

Cluster 1

Show
dados[dados$clusterg2 == 1,]$Jogador
 [1] "A7CARRILHOc33" "BTRmRATOOBOY"  "DWGuizao"      "iGADRiAN27"   
 [5] "iGDIEGO7"      "iGMAGRELINssj" "iNCOnenebete"  "iNCOsquaash"  
 [9] "INF99FeederaL" "INFLiLBOY"     "LoopsAYALA"    "LoopsCARDOZIN"
[13] "LoopsCH1EFF"   "LoopsMYTHIC44" "RiseDUDU"      "RiseNUNES"    

Cluster 4

Show
dados[dados$clusterg2 == 4,]$Jogador
[1] "A7REVOO77K" "INFlaw"     "INFLorraN" 

Cluster 5

Show
dados[dados$clusterg2 == 5,]$Jogador
[1] "BTRmOBSCURE1"

Cluster 15

Show
dados[dados$clusterg2 == 15,]$Jogador
[1] "SoulsNetto21k"