Test du χ² (Khi2 ou Chi2)

en langage python

Khi2 d'indépendance en langage python

Le Khi2 d'indépendance est un grand classique pour savoir si deux variables qualitatives sont liées.

Prenons un exemple simple : le salaire dans une entreprise est-il lié au sexe ?

Etape 0 - les données

1) SIMULATION SIMPLE - Simulons un jeu de données correspondant aux répartitions des salariés dans une entreprise, par sexe et par catégorie de salaire :

SIMULATION SIMPLE - Simulons un jeu de données correspondant aux répartitions des salariés dans une entreprise, par sexe et par catégorie de salaire :

import pandas as pd

hommes = pd.Series([50,70,110,60])

femmes = pd.Series([80,75,100,30])


matrice = pd.DataFrame({"Hommes":hommes,"Femmes":femmes})

matrice.index = ["1000 à 2000 €","2000 à 3000 €","3000 à 4000 €","4000 à 5000 €"]

matrice = matrice.T

print(matrice)

Voilà à quoi ressemblent ces données :

1000 à 2000 € 2000 à 3000 € 3000 à 4000 € 4000 à 5000 €

Hommes 50 70 110 60

Femmes 80 75 100 30

Remarque importante : en général, je n'ai pas ce tableau de contingent tout prêt : je vais plutôt avoir une variable qui donne le salaire et une autre le sexe des individus. JE DOIS DONC AVANT TOUT KHI2 CREER MON TABLEAU DE CONTINGENT : fonction crosstab. Voici un exemple :

2) SIMULATION DE DONNEES PLUS REALISTES - Quand il faut faire soi-même ses contingents en croisant deux variables qualitatives

import pandas as pd


Simulation des valeurs

import pandas as pd

from numpy.random import *

# Simulations de salaires et de sexes.

salaires= pd.Series(list(normal(loc=2500, scale=1000, size=200))+list(normal(loc=2200, scale=1200, size=300)))

salaires = salaires.round()

sex = pd.Series(["M"]*200+300*["F"])

tableau = pd.concat([salaires,sex],axis=1);

print(tableau.head(3))

Le problème est que le khi2 ne peut confronter que des effectifs croisés : variable catégorielle versus catégorielle, qualitative versus qualitative.

Il faut donc dans ce cas, définir des catégories de salaires :

type_salaires = salaires

for i in range(len(type_salaires)) :

if type_salaires[i] <= 2000 :

type_salaires[i] = "1000 à 2000 €"

elif type_salaires[i] <= 3000 :

type_salaires[i] = "2000 à 3000 €"

elif type_salaires[i] <= 4000 :

type_salaires[i] = "3000 à 4000 €"

else :

type_salaires[i] = "4000 à 5000 €"


tableau = pd.concat([tableau,type_salaires],axis=1);

tableau.columns = ["Salaires","Sexe","Types_salaire"]

print(tableau.head(7))

On peut donc ensuite croiser les données pour arriver au-même type de résultat prêt à être étudié par khi² que ci-dessus :

matrice= pd.crosstab(tableau.Sexe, tableau.Types_salaire,rownames=["Sexe"],colnames=["Salaires"])

2.1) On part de données brutes : salaire et sexe

0 1

0 1747.0 M

1 1539.0 M

2 1437.0 M

3 1855.0 M

4 1573.0 M

Affichage des premières lignes

2.2) On traite la donnée numérique pour avoir une autre variable qualitative

Salaires Sexe Types_salaire

0 1957.0 M 1000 à 2000 €

1 3546.0 M 3000 à 4000 €

2 1568.0 M 1000 à 2000 €

3 3299.0 M 3000 à 4000 €

4 1845.0 M 1000 à 2000 €

5 856.0 M 1000 à 2000 €

6 1815.0 M 1000 à 2000 €

Affichage des données dont les deux variables catégorielles "Sexe" et "Types_salaire" que l'on va pouvoir lier ou non lors d'un khi2.

2.3) On obtient des données regroupées prêtes à être analysées par khi2 d'indépendance pour voir s'il y a un lien entre sexe et niveau de salaire.

Salaires 1000 à 2000 € 2000 à 3000 € 3000 à 4000 € 4000 à 5000 €

Sexe

F 127 98 52 23

M 59 73 51 17

Etape 1 - Faire le Khi2 d'indépendance

from scipy.stats import chi2_contingency as chi2_contingency

khi2, pval , ddl , contingent_theorique = chi2_contingency(matrice)

On va considérer qu'il existe un lien entre sexe et salaire si la p-value est inférieur à 0,05 (ou moins, selon).

print(pval)

Ici, la p-value est très inférieur à 0.05, on considère donc qu'il existe un lien entre le sexe et le salaire : il y a dépendance.

On estime ainsi qu'on augmente la probabilité d'avoir une femme si le salaire est bas par exemple, ou la probabilité d'avoir un salaire élevé si on a un homme.

Rappel : la p-value ici s'intéresse à l'hypothèse nulle qui dirait qu'il n'y a pas de lien entre sexe et salaire.

La p-value traduit la probabilité d'observer une telle répartition si cette hypothèse est vraie. Si la p-value est faible, c'est qu'il est peu probable d'observer ce que l'on observe avec l'hypothèse nulle vraie, on va donc supposer que l'hypothèse alternative (lien entre sexe et salaire) est vraie, ou plutôt vraisemblablement vraie.

Khi2 de conformité en langage python

# Khi2 de conforité

obs = np.array([[16,45, 20]]).T

freq_theo = np.array([0.25,0.5,0.25]) # On attend 25%, 50% et 25% pour les différents effectifs

theo = freq_theo*sum(obs) ; print(theo)

print(stats.chisquare(f_obs=obs , f_exp=theo))

Cet exemple est à creuser car il renvoie une p-value par valeur de l'effectif. Peut-être faut-il envisager de rechercher un autre module ou d'émuler la fonction chisq.test de R (très contrôlée) avec Rpy2.