Test du khi carré d’indépendance
Testez l’indépendance de deux variables catégorielles à l’aide de chi2_contingency sur un tableau de fréquences croisé.
Test du khi carré d’indépendance est une leçon Pandas & NumPy Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Pandas & NumPy Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Pandas & NumPy Academy comprend 4 leçons au total.
Tester les relations entre variables catégorielles
Le test du khi carré d'indépendance vérifie si deux variables catégorielles sont statistiquement indépendantes ou s'il existe une association entre elles. Par exemple : « La résiliation par le client est-elle indépendante du niveau d'abonnement ? » ou « La préférence pour un produit est-elle indépendante de la tranche d'âge ? » Contrairement aux tests t, qui comparent des moyennes numériques, les tests du khi carré comparent les fréquences observées dans un tableau de contingence aux fréquences que nous attendrions si les variables étaient indépendantes.
Construire un tableau de contingence avec Pandas
Un tableau de contingence (également appelé tableau croisé) indique le nombre d'observations pour chaque combinaison de deux variables catégorielles. pd.crosstab(df['var1'], df['var2']) construit directement ce tableau à partir d'un DataFrame. Chaque cellule contient le nombre d'observations où la catégorie de ligne et la catégorie de colonne apparaissent ensemble. Ce tableau constitue l'entrée de scipy.stats.chi2_contingency().
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({
'subscription': np.random.choice(['free', 'basic', 'pro'], 300),
'churned': np.random.choice(['yes', 'no'], 300, p=[0.3, 0.7])
})
# Build contingency table
ct = pd.crosstab(df['subscription'], df['churned'])
print(ct)
print()
print('Row totals:', ct.sum(axis=1).to_dict())Exécuter chi2_contingency()
scipy.stats.chi2_contingency(observed) prend le tableau de contingence observé (sous forme de tableau NumPy ou de DataFrame Pandas) et renvoie quatre valeurs : la statistique du khi carré, la valeur p, les degrés de liberté et le tableau des fréquences attendues. L'hypothèse nulle est H₀: the two variables are independent. Si p ≤ 0.05, nous rejetons l'indépendance et concluons qu'il existe une association statistiquement significative.
import pandas as pd
import numpy as np
from scipy import stats
np.random.seed(0)
df = pd.DataFrame({
'tier': np.random.choice(['free', 'basic', 'pro'], 300),
'churned': np.random.choice(['yes', 'no'], 300, p=[0.3, 0.7])
})
ct = pd.crosstab(df['tier'], df['churned'])
chi2, p, dof, expected = stats.chi2_contingency(ct)
print(f'Chi-squared: {chi2:.3f}')
print(f'p-value: {p:.4f}')
print(f'Degrees of freedom: {dof}')
print('Association significant?', 'Yes' if p < 0.05 else 'No')Comprendre les fréquences attendues
Les fréquences attendues représentent l'aspect que prendraient les effectifs des cellules si les deux variables étaient parfaitement indépendantes. Pour chaque cellule, expected = (row_total × column_total) / grand_total. La statistique du khi carré mesure la somme des différences au carré entre les effectifs observés et attendus, normalisée par les effectifs attendus. Une valeur élevée du khi carré signifie que les effectifs observés s'écartent fortement de l'indépendance ; une valeur faible signifie que les données sont compatibles avec l'indépendance.
import pandas as pd
import numpy as np
from scipy import stats
observed = pd.DataFrame({
'converted': [50, 30],
'not_converted': [150, 170]
}, index=['variant', 'control'])
chi2, p, dof, expected = stats.chi2_contingency(observed)
print('Observed:')
print(observed)
print()
print('Expected (under independence):')
print(pd.DataFrame(expected,
index=observed.index,
columns=observed.columns).round(1))Degrés de liberté du khi carré
Pour un tableau de contingence comportant r lignes et c colonnes, le nombre de degrés de liberté est df = (r-1) × (c-1). Un tableau 2×2 possède df=1 ; un tableau 3×4 possède df=6. La valeur critique du khi carré augmente avec le nombre de degrés de liberté : pour df=1 avec α=0.05, la valeur critique est ≈ 3.84 ; pour df=6 avec α=0.05, elle est ≈ 12.6. La fonction chi2_contingency gère cela automatiquement, mais connaître la formule vous aide à comprendre pourquoi le khi carré de tableaux plus grands doit atteindre des valeurs plus élevées pour être significatif.
from scipy import stats
# Critical values of chi-squared for alpha=0.05
for df in [1, 2, 3, 4, 6, 9]:
critical = stats.chi2.ppf(0.95, df=df)
print(f'df={df}: critical value = {critical:.3f}')L'hypothèse d'une fréquence attendue minimale
Le test du khi carré n'est fiable que lorsque toutes les fréquences attendues sont au moins égales à 5 (certaines sources indiquent au moins 1, avec au plus 20 % de valeurs inférieures à 5). De petits effectifs attendus rendent l'approximation du khi carré inexacte. Lorsque cette hypothèse n'est pas respectée, utilisez le test exact de Fisher (scipy.stats.fisher_exact()) pour les tableaux 2×2, ou regroupez les catégories rares afin d'augmenter les effectifs attendus. Examinez toujours la matrice des fréquences attendues renvoyée par chi2_contingency.
import numpy as np
from scipy import stats
# Table with small expected counts
observed = np.array([[2, 3], [100, 95]])
chi2, p, dof, expected = stats.chi2_contingency(observed)
print('Expected frequencies:')
print(expected)
print('Min expected:', expected.min())
if expected.min() < 5:
print('Warning: Expected frequency < 5. Use Fisher\'s exact test.')
odds_ratio, p_fisher = stats.fisher_exact(observed)
print(f'Fisher\'s exact p: {p_fisher:.4f}')Test exact de Fisher pour les petits échantillons
scipy.stats.fisher_exact(table) calcule la probabilité exacte d'observer le tableau 2×2 donné (ou un tableau encore plus extrême) sous l'hypothèse nulle d'indépendance, sans aucune approximation. Il est toujours valide, quelle que soit la taille de l'échantillon ou l'effectif des cellules : la valeur p est exacte et non approximative. Son coût est d'ordre computationnel : il énumère tous les tableaux possibles, ce qui le rend lent pour les grands totaux. Pour les tableaux 2×2 dont l'une des cellules a un effectif inférieur à 5, préférez toujours le test exact de Fisher au khi carré.
import numpy as np
from scipy import stats
# Small clinical trial: treatment vs. outcome
observed = np.array([
[3, 12], # treated: 3 improved, 12 did not
[1, 18] # control: 1 improved, 18 did not
])
odds_ratio, p = stats.fisher_exact(observed, alternative='two-sided')
print(f'Odds ratio: {odds_ratio:.3f}')
print(f'p-value: {p:.4f}')
print('Association significant?', 'Yes' if p < 0.05 else 'No')Mesurer la force de l'association : V de Cramér
Comme pour le d de Cohen dans les tests t, la statistique du khi carré seule ne mesure pas la force de l'association : elle est amplifiée par la taille de l'échantillon. Le V de Cramér normalise le khi carré sur une échelle de 0 à 1 : 0 signifie l'absence d'association et 1 une association parfaite. V = sqrt(chi2 / (n × min(r-1, c-1))). Repères : < 0.1 indique une association faible, 0.1–0.3 une association modérée et > 0.3 une association forte. Indiquez toujours le V de Cramér avec la valeur p pour obtenir une vue d'ensemble complète.
import pandas as pd
import numpy as np
from scipy import stats
np.random.seed(0)
df = pd.DataFrame({
'tier': np.random.choice(['free', 'basic', 'pro'], 500),
'churn': np.random.choice(['yes', 'no'], 500, p=[0.3, 0.7])
})
ct = pd.crosstab(df['tier'], df['churn'])
chi2, p, dof, _ = stats.chi2_contingency(ct)
n = ct.sum().sum()
min_dim = min(ct.shape[0]-1, ct.shape[1]-1)
cramers_v = np.sqrt(chi2 / (n * min_dim))
print(f'chi2={chi2:.3f}, p={p:.4f}')
print(f'Cramer\'s V: {cramers_v:.4f}')
print('Association strength:', 'strong' if cramers_v > 0.3 else 'moderate' if cramers_v > 0.1 else 'weak')Adéquation du khi carré
Une autre application du khi carré est le test d'adéquation : il vérifie si les fréquences observées correspondent à une distribution hypothétique. Par exemple : « Les résultats d'un dé sont-ils uniformément répartis ? » ou « Le trafic de notre site web suit-il la répartition attendue selon les jours de la semaine ? » Utilisez scipy.stats.chisquare(f_obs, f_exp), où f_exp représente les fréquences attendues. L'hypothèse nulle est que les données suivent la distribution spécifiée.
import numpy as np
from scipy import stats
# Observed: counts for each weekday over 70 weeks
observed = np.array([980, 1050, 1020, 1080, 1120, 850, 900])
# Expected: uniform distribution
expected = np.full(7, observed.sum() / 7)
chi2, p = stats.chisquare(f_obs=observed, f_exp=expected)
print('Observed:', observed)
print('Expected (uniform):', expected.round(0))
print(f'chi2={chi2:.3f}, p={p:.4f}')
print('Uniform?', 'Yes' if p > 0.05 else 'No - some days significantly busier')Utiliser pd.crosstab avec normalise
Lors de la présentation des résultats d'un test du khi carré, il est utile d'afficher les proportions plutôt que les effectifs bruts, afin que les lecteurs puissent voir l'association relative. pd.crosstab(var1, var2, normalize='index') affiche la proportion par ligne (la fraction de chaque catégorie de ligne qui appartient à chaque colonne). normalize='columns' affiche les proportions par colonne. Comparer visuellement ces proportions avant d'exécuter le test vous aide à anticiper la direction de l'association et à interpréter le résultat dans son contexte.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({
'tier': np.random.choice(['free', 'basic', 'pro'], 300),
'churned': np.random.choice(['yes', 'no'], 300, p=[0.3, 0.7])
})
# Row-proportions: churn rate within each tier
prop_table = pd.crosstab(df['tier'], df['churned'], normalize='index')
print('Churn rate by tier:')
print((prop_table * 100).round(1))Test du khi carré dans les tests A/B
Le test du khi carré est le test standard pour les taux de conversion des tests A/B. Créez un tableau de contingence 2×2 avec les lignes = (groupe témoin, variante) et les colonnes = (converti, non converti). Le test du khi carré vous indique si le taux de conversion diffère significativement entre les groupes. Pour les grands échantillons, cela équivaut à un test z de comparaison de deux proportions. Pour les petits échantillons (lorsqu'un effectif attendu est < 5), utilisez plutôt le test exact de Fisher.
import numpy as np
from scipy import stats
# A/B test: control vs. variant, conversions vs. non-conversions
control_conv = 45
control_total = 500
variant_conv = 63
variant_total = 500
contingency = np.array([
[control_conv, control_total - control_conv],
[variant_conv, variant_total - variant_conv]
])
chi2, p, dof, expected = stats.chi2_contingency(contingency)
print(f'Control rate: {control_conv/control_total:.1%}')
print(f'Variant rate: {variant_conv/variant_total:.1%}')
print(f'p-value: {p:.4f}')
print('Variant significantly better?', 'Yes' if p < 0.05 else 'No')Vérification rapide
Vérifiez votre compréhension des concepts d'analyse de données présentés dans cette leçon.
Récapitulatif de la leçon
Dans cette leçon, vous avez appris que pd.crosstab() + chi2_contingency() testent si deux variables catégorielles sont indépendantes en se basant sur les fréquences observées et attendues, que le test exact de Fisher est l'alternative sûre lorsque les effectifs attendus sont inférieurs à 5, et que le V de Cramér mesure la force de l'association indépendamment de la taille de l'échantillon. Ensuite, nous comparerons les moyennes de trois groupes ou plus avec l'ANOVA et des tests post hoc.
Questions Fréquemment Posées
La leçon « Test du khi carré d’indépendance » est-elle gratuite ?
Oui — le texte complet de « Test du khi carré d’indépendance » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Pandas & NumPy Academy, passe à CoddyKit PRO. Le cours Pandas & NumPy Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Test du khi carré d’indépendance » ?
Testez l’indépendance de deux variables catégorielles à l’aide de chi2_contingency sur un tableau de fréquences croisé. Tu pratiques Pandas & NumPy Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Pandas & NumPy Academy ?
Aucune expérience préalable n'est requise. Pandas & NumPy Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.
Combien de temps prend la leçon « Test du khi carré d’indépendance » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Pandas & NumPy Academy ?
Oui. Chaque leçon Pandas & NumPy Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Statistiques descriptives et tests de normalité
- Tests t pour comparer des moyennes
- Test du khi carré d’indépendance
- ANOVA et tests post-hoc