AFC Sous Python Avec Scientisttools
AFC Sous Python Avec Scientisttools
Ce tutoriel a pour objectif de présenter rapidement les principales fonctionnalités offertes par le
package « scientisttools » pour réaliser une Analyse Factorielle des Correspondances.
Les données sur lesquelles nous allons travailler proviennent du site http://factominer.free.fr/factomethods/analy
factorielle-des-correspondances.html. Il s’agit des données issues d’un questionnaire réalisé sur
des françaises en 1974.
Ces données sont issues d’une enquête du CREDOC publiée en 1974 par Nicole Tabard, intitulée
Besoins et aspirations des familles et des jeunes. 1724 femmes ont répondu à différentes questions
à propos du travail des femmes, parmi lesquelles :
Le tableau de données est formé de deux tableaux de contingence qui croisent les réponses de la
première question à celles des deux autres.
Nous pouvons charger les données sur http://factominer.free.fr/factomethods/datasets/women_work.txt
## <class 'pandas.core.frame.DataFrame'>
## Index: 3 entries, both.man.and.woman.work to only.man.works
## Data columns (total 7 columns):
1
## # Column Non-Null Count Dtype
## --- ------ -------------- -----
## 0 stay.at.home 3 non-null int64
## 1 part-time.work 3 non-null int64
## 2 full-time.work 3 non-null int64
## 3 housewives.cut.from.world.totally.agree 3 non-null int64
## 4 housewives.cut.from.world.quite.agree 3 non-null int64
## 5 housewives.cut.from.world.quite.disagree 3 non-null int64
## 6 housewives.cut.from.world.totally.disagree 3 non-null int64
## dtypes: int64(7)
## memory usage: 192.0+ bytes
housewives.cut.from.world.totally.disagree
housewives.cut.from.world.quite.disagree
housewives.cut.from.world.totally.agree
housewives.cut.from.world.quite.agree
part-time.work
full-time.work
stay.at.home
Chaque valeur du tableau 1 correspond au nombre de femmes ayant donnée la réponse en ligne
et la réponse en colonne.
Le point de départ de l’analyse est le tableau de contingence reproduit ci-dessous.
Table 2 – Données d’enquête
C’est ce type de données (les marges des totaux mis à part) que nous fournirons à la fonction
de calcul de l’AFC.
Comme le souligne François Husson dans le MOOC Analyse des données multidimensionnelles
sur la plateforme FUN, il est difficile de savoir à partir de ce tableau si les femmes sont favorables
ou non au travail féminin. En effet, 908 femmes sur 1724, soit 52% ont répondu que la famille
idéale est celle où « Only man works ». Elles sont néanmoins 1123 sur 1724 (65%) à avoir répondu
que l’activité convenant le mieux à une mère de famille quand ses enfants vont à l’école est de
travailler à mi-temps « part-time work ». L’AFC va nous permettre d’étudier le lien entre ces
deux questions et de lever cette apparente contradiction. Elle va notamment nous permettre de
visualiser la nature de la liaison entre les deux questions. Mais qu’est ce qu’une liaison ?
2
Une liaison entre deux variables est l’écart entre les données observées et le modèle d’indépen-
dance. Mettons pour l’instant de côté cette notion, nous y reviendrons plus tard.
Objectifs
Les objectifs de l’AFC sont similaires à ceux de l’ACP : obtenir une typologie des lignes et des
colonnes et étudier le lien entre ces deux typologies.
Cependant, le concept de similarité entre les lignes et les colonnes est diférent. Ici, la similarité
entre deux lignes ou deux colonnes est complètement symétrique. Deux lignes (resp. colonnes)
sont proches l’une de l’autre si elles s’associent aux colonnes (resp. lignes) de la même façon.
On recherche les lignes (resp. colonnes) dont la distribution est la plus différente de celle de la
population. Celles qui semblent le plus ou le moins semblables.
Chaque groupe de lignes (resp. colonnes) est caractérisé par les colonnes (resp. lignes) auxquelles
il est particulièrement ou particulièrement peu associé.
Nous travaillons d’abord avec seulement les 3 premières colonnes : « Stay at home », « Part time
work » et « Full time work ».
Notons que nous pouvons calculer les marges lignes et les marges colonnes de ce tableau de
contingence de la manière suivante :
Il est aussi intéressant de calculer les pourcentages en ligne et les pourcentages en colonne.
# Pourcentages en ligne
import numpy as np
wfemmes_pourcentage_en_ligne = wfemmes.copy()
wfemmes_pourcentage_en_ligne.loc["Profil ligne moyen",:] = wfemmes.sum(axis=0)
3
wfemmes_pourcentage_en_ligne = wfemmes_pourcentage_en_ligne.apply(
lambda x : 100*x/np.sum(x),axis=1)
wfemmes_pourcentage_en_ligne.loc[:,"Total"] = wfemmes_pourcentage_en_ligne.sum(
axis=1)
Pour rappel, la ligne « Profil ligne moyen » correspond à la répartition en pourcentage des
modalités à la question sur « l’activité qui convient le mieux à une mère de famille quand les
enfants vont à l’école », quelque soit la réponse à la question sur la famille idéale. Le profil ligne
moyen peut être comparé aux profils lignes (la répartition en pourcentages ou la distribution
de probabilité d’une modalité en ligne). Ici, aucun des trois profils lignes n’est proche du profil
ligne moyen.
Calculons maintenant le tableau des pourcentages en colonne
# Pourcentage en colonne
wfemmes_pourcentage_en_colonne = wfemmes.copy()
wfemmes_pourcentage_en_colonne.loc[:,"Profil colonne moyen"] = wfemmes.sum(axis=1)
wfemmes_pourcentage_en_colonne = wfemmes_pourcentage_en_colonne.apply(
lambda x : 100*x/np.sum(x),axis=0)
wfemmes_pourcentage_en_colonne.loc["Total",:] = wfemmes_pourcentage_en_colonne.sum(
axis=0)
Ce tableau permet de constater que la répartition des réponses sur la famille idéale pour la
modalité « Part-time work » est le plus proche de la répartion des réponses à la question sur la
famille idéale. Autrement dit, le profil colonne « Part-time work » est le profil colonne le plus
proche du profil colonne moyen. Cette similitude se traduira sur le graphe de l’AFC comme nous
le verrons plus loin.
Nous verrons également que l’on passera en paramètre à la fonction Python de calcul de l’AFC,
le tableau de contingence. Mais l’AFC travaille en réalité sur le tableau de probabilités que l’on
peut calculer en divisant les valeurs du tableau de contingence par le nombre d’individus (on
effectue le calcul sur le tableau de contingence avec marge pour mieux constater que l’effectif
total du tableau de probabilité est bien égal à 1, ce qui est la marque d’une distribution de
probabilités) :
4
# Tableau des probabilités
wfemmes_tableau_de_probabilite = wfemmes_avec_marges/1724
Rappellons que notre objectif est de visualiser la nature de la liaison entre deux variables qua-
litatives. Mais faut-il encore que cette liaison soit significative. Pour ce faire, nous réalisons un
test du Khi2.
Test du χ2
Le test du χ2 mesure la significativité d’une liaison mais pas son intensité. Afin de réaliser ce
test du χ2 , nous utilisons la fonction chi_contingency de scipy.
La fonction chi_contingency nous donne, entre autres, la valeur du χ2 qui est un indicateur
de la significativité de la liaison. Mais ce qui nous interesse ici est la p-value. Nous voyons ici
que la p-value est égale à 2.4102475 × 10−49 . Cela signifie que la probabilité que les variables
soient indépendantes est égale à 2.4102475 × 10−49 . Ce qui nous permet de rejeter l’hypothèse
d’indépendance entre les deux variables. Pour autant, cela ne veut pas dire que les variables
soient dépendantes. Les réponses à la question sur la famille idéale sont probablement liées aux
réponses concernant l’activité convenant le mieux à une mère de famille dont les enfants vont à
l’école.
Test de χ2 - Explications
Le test du χ2 permet de déterminer la probabilité que les deux variables d’un tableau de contin-
gence soient indépendantes, c’est-à-dire qu’il n’existe pas de relation entre les modalités en
ligne et les modalités en colonne (les unes ne conditionnent pas les autres, et réciproquement).
Dit autrement et comme le rappelle très clairement Julien Barnier, cela veut dire que le « fait
d’appartenir à une modalité de la première variable n’a pas d’influence sur la modalité d’ap-
partenance de la deuxième variable ». Dans ce test, l’hypothèse nulle (H0) suppose qu’il y a
indépendance entre les deux variables. Si nous acceptons l’hypothèse d’indépendance (H0), nous
n’aurons pas d’utilité à réaliser une AFC car les points projetés seront extrêmement proches ou
5
confondus avec le centre de gravité, confondus avec le centre du graphe. Si nous rejetons l’hy-
pothèse d’indépendance (p-value < 0, 05), l’hypothèse alternative (H1) suppose que la liaison
entre les deux variables est significative sans que nous puissions définir l’intensité de la liaison.
Rappelons que pour que le test du χ2 soit opératoire, il doit respecter un certain nombre de
conditions (pour reprendre les propos de Claude Grasland) :
— L’effectif total du tableau de contingence doit être supérieur ou égal à 20.
— L’effectif marginal du tableau de contingence doit toujours être supérieur ou égal à 5.
— L’effectif théorique des cases du tableau de contingence doit être supérieur à 5 dans 80%
des cases du tableau de contingence.
Du fait que nous ayons obtenu une p-value égale à 2.4102475×10−49 et, par extension, inférieure
au seuil de 0, 05, nous rejetons l’hypothèse d’indépendance entre les deux variables.
Le test du χ2 est symétrique. Les lignes et les colonnes du tableau croisé sont interchangeables.
Le résultat du test sera exactement le même. Il n’y a pas de « sens de lecture » du tableau.
Nous pouvons afficher le tableau d’indépendance (tableau des effectifs théoriques) en sélection-
nant la valeur expected. Dans ce contexte, nous calculons le tableau des pourcentages théoriques,
en multipliant pour chaque case la proportion observée dans la population des deux modalités
correspondantes. Puis, le tableau des effectifs théoriques se calcule en multipliant le tableau des
pourcentages théoriques par l’effectif total.
Le tableau des effectifs théoriques n’a que peu d’intérêt en lui-même mais en a davantage com-
parativement au tableau des données observées.
Nous pouvons aussi afficher le tableau des résidus standardisés (tableau des écarts à l’indépen-
dance). Un résidu standardisé positif signifie que les effectifs dans la case sont supérieur à ceux
attendus sous l’hypothèse d’indépendance. Et l’inverse pour un résidu standardisé négatif.
# Residus standardisés
standardized_residuals = (wfemmes - effectif_theorik)/np.sqrt(effectif_theorik)
6
Exprimé d’une autre manière, l’écart à l’indépendance représente l’écart entre l’effectif observé
et l’effectif théorique, et ceci pour chacune des cases du tableau de contingence. D’ailleurs,
comme le note Philippe Cibois, l’écart à l’indépendance « est un effectif et c’est un invariant,
indépendant du choix des lignes et des colonnes (c’est la différence entre l’effectif observé et
l’effectif théorique : le résultat est donc un effectif). » Par ailleurs,
— Un écart à l’indépendance positif correspond à une attraction entre les deux modalités
pour la case observée.
— À l’inverse, un écart à l’indépendance négatif correspond à une opposition entre les deux
modalités pour la case observée.
Plus la valeur de l’écart à l’indépendance est importante, plus l’attraction/opposition entre les
modalités est forte.
AFC
Notre objectif est bien de visualiser la nature de la liaison entre les deux variables qualitatives.
Sachant qu’une liaison correspond à l’écart entre les données observées et le modèle d’indépen-
dance, nous souhaitons donc visualiser la nature de l’écart à l’indépendance entre deux variables
qualitatives.
Par ailleurs, il y a trois façons de caractériser la liaison entre les deux variables qualitatives.
— La significativité de la liaison (qui se mesure avec le test du χ2 ).
— L’intensité de la liaison (qui se mesure, entre autre, avec le ϕ2 ).
— La nature de la liaison (qui correspond à l’association entre les modalités et qui est
représentée par le biais de l’AFC).
Le test du χ2 a permis d’écarter l’hypothèse d’indépendance. Il y a donc une liaison entre les
modalités des deux variables. De fait, nous pouvons faire une AFC pour visualiser la nature
de la liaison. Pour notre part, nous avons choisi d’utiliser le package « scientisttools » (dédié à
l’analyse multidimensionnelle de données).
On utilisera les trois première colonnes (correspondant aux réponses de la deuxième question)
comme variables actives et les quatre dernières (correspondant à la troisième question) comme
variables illustratives.
Nous chargeons donc la librairie « scientisttools »
# Chargement de la librairie
from scientisttools.decomposition import CA
Lors du précédent test du χ2 , nous avons obtenu une p-value égale à 2.4102475 × 10−49 . Nous
avons donc rejeté l’hypothèse d’indépendance entre les deux variables et admis que la liaison
entre ces deux variables est significative. Nous sommes en droit de réaliser une AFC afin de
visualiser la nature de la liaison. Pour ce faire, nous allons employer la fonction CA, fournie par
le package « scientisttools ».
On crée une instance de la classe CA, en lui passant ici des étiquettes pour les lignes et les
colonnes. Ces paramètres sont facultatifs ; en leur absence, le programme détermine automati-
quement des étiquettes.
7
# Instanciation du modèle
my_ca = CA(n_components=None,
row_labels=wfemmes.index,
col_labels=wfemmes.columns,
row_sup_labels=None,
col_sup_labels=None)
Valeurs propres
# Valeurs propres
print(my_ca.eig_)
## [[1.16840024e-01 1.85604492e-02]
## [9.82795752e-02 nan]
## [8.62921829e+01 1.37078171e+01]
## [8.62921829e+01 1.00000000e+02]]
# Valeurs propres
from scientisttools.extractfactor import get_eig
print(get_eig(my_ca))
8
from scientisttools.ggplot import fviz_eigenvalue
print(fviz_eigenvalue(my_ca,choice="eigenvalue"))
Scree plot
0.12
0.09
Eigenvalue
0.06
0.03
0
1 2
Dimensions
print(fviz_eigenvalue(my_ca,choice="proportion"))
Scree plot
75
Percentage of explained variances
50
25
0
1 2
Dimensions
9
On peut obtenir un résumé des principaux résultats en utilisant la fonction summaryCA.
Représentation graphique
10
Row points - CA
both.man.and.woman.work
0.2
0.1
Dim.2 (13.71%)
only.man.works
0.1
man.morks.more
Columns points - CA
0.2 full-time.work stay.at.home
0.1
Dim.2 (13.71%)
0.1 part-time.work
11
Le nuage des colonnes montre que le premier axe oppose « Stay at home » et « Full-time work »,
ce qui signifie qu’il oppose deux profils de femmes. Les femmes qui ont répondu « Stay at home »
ont répondu « Only husband works » plus souvent que l’ensemble de la population et « Both
husband and wife work » moins souvent que l’ensemble de la population.
De même, les femmes qui ont répondu « Full-time work » ont répondu « Only husband works »
moins souvent que l’ensemble de la population et « Both husband and wife work » plus souvent
que l’ensemble de la population. Le premier axe ordonne les modalités de la deuxième question
de la moins à la plus en faveur du travail des femmes.
La même interprétation peut être faite pour le premier axe du nuage des lignes. Les modalités
sont triées de la moins (« Only husband works ») à la plus (« Both husband and wife work »)
en faveur du travail des femmes.
On peut représenter à la fois les lignes et les colonnes.
Factor map
0.25
both.man.and.woman.work
0.20full-time.work
stay.at.home
0.15
0.10
Dim 2 (13.71%)
0.05 only.man.works
0.00
0.05
0.10 part-time.work
0.15
man.morks.more
0.6 0.4 0.2 0.0 0.2 0.4 0.6
Dim 1 (86.29%)
« Stay at home » est associé à « Only husband works » et peu associé aux deux autres modalités.
« Both husband and wife work » est associé à « Full-time work » et opposé à « Stay at home ».
Revenons un instant sur les données du tableau 1, issu de l’enquête de Nicole Tabard, croisant
les deux variables qualitatives (questions) :
— Quelle est la famille idéale pour vous ?
— Quelle activité convient le mieux à une mère de famille quand ses enfants vont à l’école ?
Il est important de rappeler que les résultats de cette enquête ont été publiés en 1974. Il est fort
à parier que la répartition des réponses serait totalement, si ce n’est en grande partie, différente
aujourd’hui.
12
Lors d’une première lecture de ce tableau de contingence, François Husson soulève une apparente
contradiction. À la question « Quelle est la famille idéale pour vous ? », nous voyons que 908
femmes sur 1724 (visible dans la marge colonne), soit environ 53% des répondantes, déclarent
« Only man works » et seulement 261 femmes sur 1724 (environ 15%) déclarent « Both man and
woman work ». Sur la base de ces premières réponses, nous pouvons émettre l’hypothèse, qu’à
cette époque, une majorité était en faveur d’un modèle familial où seul le mari travaille.
À côté de ça, à la question « Quelle activité convient le mieux à une mère de famille quand ses
enfants vont à l’école ? », elles sont 1440 sur 1724 (visible dans la marge ligne), soit environ 84%,
à être en faveur du travail à mi-temps « Part time work » ou à plein-temps « Full time work ».
Les réponses à cette question semblent indiquer que les femmes sont moins hostiles au travail
féminin (bien au contraire).
Du coup, à ce stade de l’interprétation, nous nous retrouvons a priori face une contradiction.
De cela, nous pouvons dire que le tableau de contingence ne permet pas de savoir si les femmes
des années 70 sont favorables ou non à l’activité féminine. Par contre, Une première lecture du
graphe de l’AFC nous permet de dire que les modalités des réponses s’associent entre elles des
plus favorables au travail féminin aux plus défavorables au travail féminin.
Avant d’approfondir, plus en détail, l’interprétation de cette AFC, nous allons faire un pas de
côté et voir ce qui se passe dans le cas où il y aurait indépendance entre les deux variables.
Si nous réalisons une AFC avec les données du modèle d’indépendance, on obtient la figure
suivante :
Factor map
0.04
0.02
Dim 2 (nan%)
0.00 both.man.and.woman.work
man.morks.more
only.man.works
part-time.work
full-time.work
stay.at.home
0.02
0.04
La lecture de ce graphique nous permet de voir que les points sont quasiment tous confondus
avec le centre de gravité, correspondant au profil moyen. La représentation graphique est trom-
peuse mais l’échelle des axes va dans le sens de notre interprétation. Simplement, ce qu’il y
13
a retenir de ce graphe, c’est que, lorsqu’il y a indépendance entre les deux variables, tous les
points sont confondus avec l’origine. Du fait qu’il n’y ait pas d’écarts à l’indépendance, il n’y
a graphiquement rien à exploiter, rien à interpréter, rien à analyser. Ce graphe donne à voir ce
que nous avons précédemment énoncé, à savoir que :
— Si nous acceptons l’hypothèse d’indépendance (p-value > 0.05 dans le cas d’un test du χ2 ),
nous n’aurons pas d’utilité à réaliser une AFC car les points projetés seront extrêmement
proches ou confondus avec le centre de gravité, confondus avec le centre du graphe.
— La réalisation d’un test du χ2 est donc fortement conseillée avant la réalisation d’une
AFC.
— Plus précisément, le test du χ2 conditionne l’éventuelle réalisation d’une AFC.
On ajoute les colonnes qui correspondent à la troisième question en tant que variables illustra-
tives. Tapez :
14
Columns points - CA
0.20
full-time.work
stay.at.home
0.15
0.10 housewives.cut.from.world.totally.disagree
Dim.2 (13.71%)
0.05
housewives.cut.from.world.quite.disagree
0.00
housewives.cut.from.world.totally.agree
0.05
housewives.cut.from.world.quite.agree
0.10 part-time.work
« Totally agree » et « Quite agree » pour « Women who do not work feel cut off from the world »
sont proches des modalités en faveur du travail des femmes.
« Quite disagree » et « Totally “disagree » sont proches des modalités opposées au travail des
femmes.
Pour ajouter des points lignes illustratifs, utilisez l’argument suivant de la fonction PCA :
row_sup_labels
Tous les résultats détaillés peuvent être vus dans l’objet my_pca2. On peut récupérer les valeurs
propres, les résultats des points lignes actifs et illustratifs, les résultats des points colonnes actifs
et supplémentaires en tapant :
15
row = get_ca_row(my_ca2)
print(row.keys())
col = get_ca_col(my_ca2)
print(col.keys())
Des graphiques qui permettent d’interpréter rapidement les axes : on choisit un axe factoriel (le
1er axe dans notre exemple) et on observe quels sont les points lignes et colonnes qui présentent
les plus fortes contributions et cos2 pour cet axe.
only.man.works
individuals
both.man.and.woman.work
man.morks.more
0 10 20 30 40
Contributions (%)
16
Contribution of continues variables to Dim-1
stay.at.home
continues variables
full-time.work
part-time.work
0 10 20 30 40 50
Contributions (%)
# Classement des points lignes en fonction de leur cos2 sur le 1er axe
fig,axe = plt.subplots(figsize=(16,10))
plot_cosines(my_ca2,choice="ind",axis=0,top_cos2=10,ax=axe)
plt.show()
only.man.works
individuals
both.man.and.woman.work
man.morks.more
# Classement des points colonnes en fonction de leur cos2 sur le 1er axe
fig,axe = plt.subplots(figsize=(16,10))
plot_cosines(my_ca2,choice="var",axis=0,ax=axe)
plt.show()
17
Cosinus of continues variables to Dim-1
full-time.work
part-time.work
18