Discrétiser une variable quantitative pour en faire une catégorielle

en langage R

L'essentiel de cette page

Comment discrétiser objectivement une variable.

Dois-je prendre les quantiles ? Ce ne serait pas nécessairement pertinent. Car, si j'ai deux catégories avec des bons et des mauvais et que j'ai plus de mauvais que de bons, couper en deux mon groupe serait une grosse erreur.

Il existe des critères objectifs pour déterminer le nombre optimal de catégories (CAH) et les seuils pour les séparer par la méthode des ruptures naturelles de Jenks (Jenks natural breaks optimization).

Voici un exemple.

J'ai les notes d'élèves qui vont de 0 à 20.

Je les ai simuler pour faire 3 groupes, l'un qui tourne autour de 5 de moyenne, l'autre de 10 (la majorité) et quelques uns autour de 14.

Si je voulais discrétiser ces notes en "bon" et "mauvais" ou "bon", "moyen" et "mauvais", qu'est-ce qui est le plus pertinent : 2, 3, 4 catégories ? A partir de quelles notes ?

Pour simuler les notes :

x <- c(rnorm(50,10,3),rnorm(20,14,4),rnorm(30,5,4))

x <- ifelse(x<0,0,x) # Pas de notes sous 0

x <- ifelse(x>20,20,x) # Pas de notes au-dessus de 20

x <- round(x,0) # On arrondi

1- Déterminer le nombre optimal de catégories

Le mieux est de faire tourner un algorithme de clustering hiérarchique ascendant qui va établir le nombre de catégories optimal grâce à un diagramme d'inertie.

Chaque grosse marche sur ce diagramme suggère une grande séparation entre les données.

Dans cet exemple : 2, 3 voir 5 catégories, pas plus, certainement pas 4.

# Clusterisation

myclust <- hclust(dist(x, method = "euclidean"), method = "ward.D2")

# Calcul de l'inertie (les hauteurs des fusions dans le clustering)

inertie <- sort(myclust$height, decreasing = TRUE)

# Calcul des différences d'inertie entre chaque fusion

diff_inertie <- diff(inertie)

# Trouver la plus grande différence (le "saut" le plus important dans l'inertie)

# On travaille sur les intervalles 2 à 4 car on envisage 3 à 5 catégories

optimal_clusters <- which.min(diff_inertie[2:4]) + 2  # Ajouter 1 car l'indice renvoie au point avant la coupure

# Affichage de l'inertie pour les 20 premières fusions

plot(inertie[1:20], type = "s", 

ylab="Inertie",

xlab = "", lwd=2, 

main="Nombre de catégories la plus proable",

sub=paste("Le nombre optimal de catégories est :", optimal_clusters, "\n"))

grid()

points(optimal_clusters,inertie[optimal_clusters],pch=16,cex=2,col="red")

2- Déterminer les valeurs seuil entre les catégories

La méthode des ruptures naturelles de Jenks permet de proposer des seuils qui séparent le bon nombre de catégories en minimisant la variances au sein des catégories et maximisant la variance entre catégories.

Ici, on retrouve bien 3 catégories dont les seuils sont pour les notes de 5 et 11 et qui vont séparer les "Faibles", "Moyens", "Bons".

install.packages("classInt")

library(classInt)

# Appliquer Jenks Natural Breaks avec un nombre maximum de catégories

jenks_breaks <- classIntervals(x, n = optimal_clusters, style = "jenks")

# Obtenir les points de coupure

breaks <- jenks_breaks$brks

print(breaks) # 0  5 11 20

# Générer des couleurs pour chaque catégorie (une couleur par intervalle)

bar_colors <- rainbow(length(breaks) - 1)

# Visualiser l'histogramme avec les barres colorées par catégorie

hist(x, breaks = breaks, freq = FALSE,ylim=c(0,0.12),

col = bar_colors, border = "white",

main = paste("Catégories retenues pour les notes des élèves"), xlab = "Notes")

# Ajouter la densité par-dessus

lines(density(x), col = "blue", lwd = 2)

# Ajouter des lignes verticales pour visualiser les points de coupure

abline(v = breaks, col = "blue", lty = 2, lwd = 2)

hist(x, freq=FALSE, col="white", border="red", lwd=3,

main = "Répartition des notes des élèves")

lines(density(x),col="blue",lwd=3)

Imaginons maintenant des données où l'on aurait eu des catégories plus nettes avec des élèves en train de décrocher (~4), d'autres moyens (~8), puis des bons (~13) et des excellents (~19).

L'algorithme trouve ces catégories et sépare les élèves sur les seuils de 9, 15 et 19 ce qui est pas mal.