L'ACP des variables qualitatives. L'AFC transforme un tableau croisé (mots par note, produits par région) en une carte où les modalités qui s'attirent sont proches. L'ACM étend le principe à tout un questionnaire. C'est l'outil de référence des études et des enquêtes en France.
Un plan de table de mariage dressé à partir de qui parle avec qui : les invités qui se fréquentent beaucoup sont placés ensemble, ceux qui s'évitent aux deux bouts de la salle.
Des effectifs : combien de fois chaque mot apparaît dans les avis notés 1, 2, 3, 4 ou 5. Pour l'ACM, on croise toutes les questions d'une enquête entre elles.
Si les mots étaient répartis au hasard entre les notes, chaque case aurait un effectif attendu. L'AFC travaille sur les écarts à cet attendu, ceux que mesure le test du khi-deux.
Une décomposition en valeurs singulières résume ces écarts en axes, du plus important au moins important. Sur la carte, un mot et une note proches s'attirent : ce mot est sur-représenté dans les avis de cette note.
Pour chaque avis, le texte libre et la note de 1 à 5. On découpe les textes en mots de 4 lettres et plus, et on garde les 74 mots cités au moins 30 fois. Le tableau croise ces mots avec les 5 notes.
Sur le jeu d'exemple, le premier axe garde 66 % de l'information et oppose les notes 1-2 (remboursement, retard, cassé) aux notes 4-5 (recommande, excellent). Le deuxième, 33 %, isole la note 3 et son vocabulaire tiède (correct, délais). Le mot « service » reste au centre du premier axe : il sert autant à se plaindre qu'à féliciter.
Le test du khi-deux vérifie d'abord que mots et notes ne sont pas indépendants. La part d'inertie de chaque axe dit ce que la carte résume : ici, les deux premiers axes en gardent 99 %. On ne commente que les points bien représentés et à forte contribution.
Pas d'hyperparamètre au sens strict : l'essentiel se joue dans la préparation du tableau. Noms donnés pour R (FactoMineR) ; en Python, le calcul se fait en quelques lignes avec numpy.
Les lignes et colonnes rares ont des profils instables qui tirent les axes. On fixe un effectif minimal (ici 30 citations par mot) ou on regroupe les modalités proches.
On garde les axes qui portent l'essentiel de l'inertie et qu'on sait interpréter. Avec 5 colonnes, il ne peut pas y en avoir plus de 4.
Des lignes ou colonnes projetées sur la carte sans participer à sa construction (row.sup, col.sup dans CA). Utile pour situer une catégorie de produit ou une période sans qu'elle influence les axes.
# Verbatims et notes : AFC en R
library(FactoMineR)
avis <- read.csv("avis_clients.csv", fileEncoding = "UTF-8")
# Mots de 4 lettres et plus, croisés avec la note (1 à 5) de l'avis
textes <- tolower(avis$texte)
mots <- regmatches(textes, gregexpr("[[:alpha:]]{4,}", textes))
long <- data.frame(mot = unlist(mots), note = rep(avis$note, lengths(mots)))
tableau <- table(long$mot, long$note)
tableau <- tableau[rowSums(tableau) >= 30, ] # mots assez fréquents
print(chisq.test(tableau))
afc <- CA(as.data.frame.matrix(tableau), graph = FALSE)
print(round(afc$eig, 3)) # valeur propre et % d'inertie de chaque axe
print(round(afc$col$coord[, 1:2], 2)) # position des notes
# Position de quelques mots (le signe d'un axe est arbitraire)
choix <- c("remboursement", "retard", "service", "correct", "délais", "recommande")
print(round(afc$row$coord[choix, 1:2], 2))
# Verbatims et notes : AFC en Python
import numpy as np
import pandas as pd
from scipy.stats import chi2_contingency
avis = pd.read_csv("avis_clients.csv")
# Mots de 4 lettres et plus, croisés avec la note (1 à 5) de l'avis
mots = avis["texte"].str.lower().str.findall(r"[a-zàâçéèêëîïôûùüÿœ]{4,}")
long = pd.DataFrame({"mot": mots, "note": avis["note"]}).explode("mot", ignore_index=True)
tableau = pd.crosstab(long["mot"], long["note"])
tableau = tableau[tableau.sum(axis=1) >= 30] # mots assez fréquents
khi2, p, ddl, _ = chi2_contingency(tableau)
print(f"Khi-deux = {khi2:.0f}, ddl = {ddl}, p = {p:.1e}")
# AFC = SVD du tableau des écarts à l'indépendance
N = tableau.values / tableau.values.sum()
r, c = N.sum(axis=1), N.sum(axis=0)
S = (N - np.outer(r, c)) / np.sqrt(np.outer(r, c))
U, s, Vt = np.linalg.svd(S, full_matrices=False)
print("Part d'inertie par axe :", (s**2 / (s**2).sum()).round(3)[:3])
# Coordonnées des notes et des mots sur les 2 premiers axes
notes_xy = pd.DataFrame(Vt[:2].T * s[:2] / np.sqrt(c)[:, None], index=tableau.columns, columns=["axe1", "axe2"])
mots_xy = pd.DataFrame(U[:, :2] * s[:2] / np.sqrt(r)[:, None], index=tableau.index, columns=["axe1", "axe2"])
print(notes_xy.round(2))
print(mots_xy.loc[["remboursement", "retard", "service", "correct", "délais", "recommande"]].round(2))
L'AFC analyse un tableau croisé entre deux variables qualitatives, comme mots et notes. L'ACM analyse simultanément plusieurs variables qualitatives, typiquement toutes les questions fermées d'un questionnaire. Techniquement, l'ACM est une AFC appliquée au tableau disjonctif complet.
Deux modalités d'une même variable proches ont des profils similaires. Un mot proche d'une note est sur-représenté dans les avis de cette note. Un point au centre a un profil moyen. On ne commente que les points bien représentés, et le signe d'un axe est arbitraire : seules les oppositions comptent.
L'ACP résume des variables numériques en axes, avec une distance euclidienne. L'AFC résume un tableau d'effectifs avec la distance du khi-deux, qui compare des profils en pourcentage. On peut voir l'AFC comme une ACP pondérée appliquée aux profils du tableau croisé.
Même logique d'axes qui résument l'information, mais pour des variables quantitatives.
Voir la fiche → le complément classiqueLancée sur les axes de l'AFC ou de l'ACM, elle regroupe répondants ou modalités en profils types.
Voir la fiche → l'autre lecture d'un tableau d'effectifsDécompose un tableau positif en thèmes additifs, plus lisibles qu'une carte quand il y a beaucoup de dimensions.
Voir la fiche →Dataistudio forme les équipes au machine learning et à l'IA, sur des cas concrets.
Nous utilisons des cookies de mesure d'audience et de suivi publicitaire pour comprendre la fréquentation du site et l'efficacité de nos annonces. Rien n'est déposé sans votre accord. En savoir plus