Estimer les progrès d’un joueur

Estimer les progrès d’un joueur de sports collectif est un sujet complexe. Il mêle l’objectif avec le subjectif. Rien de remplacera l’avis de l’entraîneur pour savoir qui doit être sur le terrain. Cependant aujourd’hui je vais vous présenter une solution avec des données objectives.

Nous allons prendre l’exemple de la NBA. 2 raisons : beaucoup de statistiques sont disponibles et il y a un trophée chaque saison pour le joueur avec la plus forte progression (en comparaison à la saison précédente).

Nous allons utiliser des statistiques ascendantes (statistiques individuelles pour expliquer la réussite collective) pour 2 joueurs (Spencer Dinwiddie et Brandon Ingram), à la date du 27 janvier 2020. Le script en langage R est disponible sur mon Github (MIP).

 install.packages("dplyr")
install.packages("ggplot2")
install.packages("reshape2")

library(dplyr) #Load readxl package
library(ggplot2) #Load readxl package
library(reshape2) #Load readxl package
library(readr)

# chargement données 2019-2020
brk20 <- read_csv("brk20.csv")
View(brk20)
brk19 <- read_csv("brk19.csv")
View(brk19)
no20 <- read_csv("no20.csv")
View(no20)
lal19 <- read_csv("lal19.csv")
View(lal19)

Nous allons charger les données et les packages nécessaires. Puis visualiser les données brutes.


Pour débuter nous allons corriger le nom de joueurs via une fonction qui séparer la colonnes en 2 parties et conserver uniquement la 1ère.

 ## Extraction nom
first = function(str){
    str = str[[1]]
    parts = strsplit(str,'\\\\')[[1]]
    first_part = parts[1]
    if(length(parts) >= 2)
      print(sprintf(' - Il y a plusieurs parties dans "%s", ne gardons que %s.',paste(parts,collapse=""),first_part))  
    return(first_part)
  }

# Correctif nom joueur
brk20['X2'] = apply(brk20['X2'], 1, first) 
brk19['X2'] = apply(brk19['X2'], 1, first) 
no20['X2'] = apply(no20['X2'], 1, first) 
lal19['X2'] = apply(lal19['X2'], 1, first) 

Puis, pour les statistiques variables selon le nombre de minutes jouées nous voulons obtenir un ratio par minute. Ceci pour éviter de donner un avantage au joueur dont les minutes auraient largement augmentées d’une saison sur l’autre. L’impact sur l’équipe pendant les minutes jouées sont importantes.

Pour cela nous allons créer une fonction qui prend 2 variables : x (la liste des statistiques à modifier) et y la variable de minutes jouées.

 # Fonction calcul stat par minutes
per_min = function(x,y){
  return(x/y)
}


# liste stats à corriger
list<-c("3P","3PA","2P","2PA","FT","FTA","ORB","DRB","TRB","AST","STL","BLK","TOV","PF","PTS")

# Application fonction à liste variables
brk20[list]<-per_min(brk20[list],brk20$MP)
brk19[list]<-per_min(brk19[list],brk19$MP)
no20[list]<-per_min(no20[list],no20$MP)
lal19[list]<-per_min(lal19[list],lal19$MP)

Normaliser les statistiques via un calcul du score Z afin d’obtenir l’impact du joueur dans son équipe. L’objectifs est d’éviter de comparer sans norme. Mais de comparer la place, statistiquement, du joueur dans son équipe. 

Puis faire un peu de nettoyage.

 # Normalisation
brk20[c(3:28)] <- scale(brk20[c(3:28)])
brk19[c(3:28)] <- scale(brk19[c(3:28)])
no20[c(3:28)] <- scale(no20[c(3:28)])
lal19[c(3:28)] <- scale(lal19[c(3:28)])

# Conservation Dinwiddie
Dinwiddie20<-brk20[brk20$X2=="Spencer Dinwiddie",]
Dinwiddie20<-Dinwiddie20[2:28]

Dinwiddie19<-brk19[brk19$X2=="Spencer Dinwiddie",]
Dinwiddie19<-Dinwiddie19[2:28]

# Conservation Ingram
Ingram20<-no20[no20$X2=="Brandon Ingram",]
Ingram20<-Ingram20[2:28]

Ingram19<-lal19[lal19$X2=="Brandon Ingram",]
Ingram19<-Ingram19[2:28]


# Retrait age 
Dinwiddie20 <- Dinwiddie20[-2]
Dinwiddie19 <- Dinwiddie19[-2]
Ingram20 <- Ingram20[-2]
Ingram19 <- Ingram19[-2]

Les données sont actuellements encore sur un tableau de données par saison et par joueurs, mais également sur plusieurs colonnes. Nous allons à présent changer d’un format large vers un format long, puis les regrouper sur un seul tableau de de données par joueurs. Ceci afin de pouvoir calculer les différences entre les 2 saisons. Nous voulons comparer les joueurs à lui même.

# Changement format données
Dinwiddie20<-melt(Dinwiddie20,  id="X2")
Dinwiddie19<-melt(Dinwiddie19,  id="X2")
Ingram20<-melt(Ingram20,  id="X2")
Ingram19<-melt(Ingram19,  id="X2")

Enfin, nous allons calculer la différences entre les 2 saisons. Nous avons à présent un tableau de données par joueurs. Nous allons tout regrouper sur un seul tableau pour finalement mettre cette différences en graphique.

#Merge
Dinwiddie<-merge(Dinwiddie19,Dinwiddie20,by=c("X2","variable"))
Dinwiddie$diff<-Dinwiddie$value.y-Dinwiddie$value.x
Ingram<-merge(Ingram19,Ingram20,by=c("X2","variable"))
Ingram$diff<-Ingram$value.y-Ingram$value.x

#Jointure
Dinwiddie_Ingram<-rbind(Dinwiddie,Ingram)

#Graphique comparaison des 2 joueurs
ggplot(Dinwiddie_Ingram,aes(x = Dinwiddie_Ingram$variable, y = Dinwiddie_Ingram$diff, fill = X2))+
  geom_bar(stat="identity", position=position_dodge())+coord_flip()+ 
  xlab("Stat en relation avec l'équipe")+ylab("Différence 2019-2020")+
  theme_classic()+ theme(legend.text = element_text(colour="blue", size=10, 
                                                    face="bold"),legend.position="top")+
  labs(fill = "Joueur")



Si la version visuelle ne vous convient pas, il est également possible de faire la somme ou la moyenne de ces différences d’une saison sur l’autre. 

# Somme et moyenne diff

sum(Dinwiddie_Ingram$diff[Dinwiddie_Ingram$X2=="Spencer Dinwiddie"]) #12.39
sum(Dinwiddie_Ingram$diff[Dinwiddie_Ingram$X2=="Brandon Ingram"]) #10.61

mean(Dinwiddie_Ingram$diff[Dinwiddie_Ingram$X2=="Spencer Dinwiddie"]) #0.4956364
mean(Dinwiddie_Ingram$diff[Dinwiddie_Ingram$X2=="Brandon Ingram"]) #0.4244306

Spencer Dinwiddie = 12.39 / 0.49

Brandon Ingram = 10.61 / 0.42

Résumons

Dans notre cas présent les deux joueurs semblent avoir un impact plus important sur leur équipes respectives cette saison. Cependant Spencer Dinwiddie semble avoir su rentabiliser son temps de jeu. En tout cas mieux de Brandon Ingram. Spencer Dinwiddie semble parfaitement exploiter la situation de son équipe et de son temps de jeu accru.