Analyse factorielle multiple des correspondances (AFCM) avec

Résumé: L'analyse factorielle multiple des correspondance (AFCM) n'est pas disponible dans la librairie scikit-learn ni dans tout autre librairie officielle. Elle est obtenue en utilisant celle plus fruste: MCA. Illustration sommaire de l'AFCM, sur des données "jouet" puis sur celles du naufrage du Titanic.

1 Disponibilité de l'AFCM

L'AFCM est une méthode proposée en France par Benzécri en 1982 avant d'être diffusée en langue anglaise de Leeuw (1985) puis par Greenacre à partir de 2005 sans pour autant être très utilisée et donc présente dans la plupart des logiciels (sauf SAS). Elle est très développée dans la librairie R factoMineR au sein de l'Agrocampus de Rennes mais absente des principales lbrairies en Python plus concernées par des données physiques, signaux ou images.

Il ne serait pas difficile de recontruire cette analyse en suivant le déroulement des calculs matriciels: SVD du tableau disjonctif complet. Néanmoins, ce qui reste le plus compliqué est la gestion des types possibles de données : table de contingence, tableau de Burt, tableau disjontif, en association ou nom à la classe DataFrame, ainsi que la production de graphiques de qualité. Il est aussi possible d'exploiter un embryon de programme: MCA en installant la librairie correspondante par la commande pip install --user mca selon l'installation, ou en chargeant le seul module mca.py dans le répertoire courant.

Comme pour l'ACP ou l'AFD, il est bienvenu de contrôler les résultats fournis sur un exemple jouet avant d'aborder des données plus complexes.

Il reste du travail pour: traiter directement un objet DataFrame, accepter des variables siupplémentaires, construire des fonction graphiques de qualité...

2 AFCM de données jouet

2.1 Lecture des données


In [ ]:
# Librairies
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

# Lire les données avec plusieurs espaces comme séparateur
# oublier la première colonne et utilisaer la première ligne pour le nom des variables
datFic=pd.read_table('Data/afcfic.dat',header=0,sep='\s+',usecols=[1,2])
datFic

In [ ]:
# Changer le type
datFic["csp"]=pd.Categorical(datFic["csp"],ordered=False)
datFic["sport"]=pd.Categorical(datFic["sport"],ordered=False)
datFic

2.2 Vérification


In [ ]:
datFic.describe()

In [ ]:
pd.crosstab(datFic["csp"],datFic["sport"])

2.3 Tableau disjonctif

La documentation de la fonction MCA est inexistante. Cette fonction peut en principe analyser un DataFrame mais la gestion de variables qualitatives complexes semble déffectueuse. Il est préférable d'anticiper en construisant les variables indicatrices (dummies).


In [ ]:
# Indicatrices
dc=pd.DataFrame(pd.get_dummies(datFic))
dc.head()

2.4 AFCM


In [ ]:
from mca import MCA
mcaFic=MCA(dc,benzecri=False)
# Valeurs singulières
print(mcaFic.L)

Q De l'AFC de quel tableau sont ces valeurs propres? (comparer avec R).

Q Que sont les tableaux ci-dessous?


In [ ]:
print(mcaFic.fs_c())

In [ ]:
print(mcaFic.fs_r())

La fonction MCA calcule également des contributions, cosinus carrés et "parts de variance expliquée".

2.5 Graphiques de l'AFCM


In [ ]:
plt.scatter(mcaFic.fs_c()[:, 0],mcaFic.fs_c()[:, 1])
for i, j, nom in zip(mcaFic.fs_c()[:, 0],mcaFic.fs_c()[:, 1], dc.columns):
       plt.text(i, j, nom)
plt.show()

In [ ]:
plt.scatter(mcaFic.fs_r()[:, 0],mcaFic.fs_r()[:, 1])
for i, j, nom in zip(mcaFic.fs_r()[:, 0],mcaFic.fs_r()[:, 1], dc.index):
       plt.text(i, j, nom)
plt.show()

3 Données Titanic

3.1 Lecture des données

Les données sur le naufrage du Titanic sont décrites dans le calepin d'introduction à Python et consacré à pandas. Reconstruire la table de données en lisant le fichier .csv.


In [ ]:
# Lire les données
df=pd.read_csv('Data/titanic.csv',skiprows=1,header=None,usecols=[1,2,4,5,9,11],
  names=["Surv","Classe","Genre","Age","Prix","Port"],dtype={"Surv":object,"Classe":object,"Genre":object,"Port":object})
df.head()

In [ ]:
df.shape # dimensions

In [ ]:
# Redéfinir les types 
df["Surv"]=pd.Categorical(df["Surv"],ordered=False)
df["Classe"]=pd.Categorical(df["Classe"],ordered=False)
df["Genre"]=pd.Categorical(df["Genre"],ordered=False)
df["Port"]=pd.Categorical(df["Port"],ordered=False)
df.dtypes

3.2 Données manquantes

Vérifier que les données contiennent des valeurs manquantes, faire des imputations à la médiane d'une valeur quantitative manquante ou la modalité la plus fréquente d'une valeur qualitative absente.


In [ ]:
df.count()

In [ ]:
# imputation des valeurs manquantes
df["Age"]=df["Age"].fillna(df["Age"].median())
df.Port=df["Port"].fillna("S")

Continuer en transformant les variables.

2.3 Transformations

Les variabels quantitatives sont découpées en classes pour exécuter ue AFCM sur toutes les variables. Les modalités des variables qualitatives sont renommées afin de pouvoir construire des graphiques explicites.


In [ ]:
# Discrétiser les variables quantitatives
df["AgeQ"]=pd.qcut(df.Age,3,labels=["Ag1","Ag2","Ag3"])
df["PrixQ"]=pd.qcut(df.Prix,3,labels=["Pr1","Pr2","Pr3"])
# redéfinir les noms des modalités 
df["Surv"]=df["Surv"].cat.rename_categories(["Vnon","Voui"])
df["Classe"]=df["Classe"].cat.rename_categories(["Cl1","Cl2","Cl3"])
df["Genre"]=df["Genre"].cat.rename_categories(["Gfem","Gmas"])
df["Port"]=df["Port"].cat.rename_categories(["Pc","Pq","Ps"])
df.head()

2.4 Analyse multiple des correspondances

Les données "Titanic" regroupent des variables qualitatives et quantitatives. Après recodage en classes (discrétisation) des variables quantitatives, la table obtenue se prête à une analyse factorielle multiple des correspondances.


In [ ]:
# Suppression des variables quantitatives
# pour l'AFCM
df_q=df.drop(["Age","Prix"],axis=1)
df_q.head()
# Indicatrices
dc=pd.DataFrame(pd.get_dummies(df_q[["Surv","Classe","Genre","Port","AgeQ","PrixQ"]]))
dc.head()

Calcul de l'AFCM et représentations graphiques.


In [ ]:
mca_df=MCA(dc,benzecri=False)
# Valeurs singulières
print(mca_df.L)

In [ ]:
# Composantes principales des colonnes (modalités)
print(mca_df.fs_c())

In [ ]:
# Premier plan principal
col=[1,1,2,2,2,3,3,5,5,5,6,6,6,7,7,7]
plt.scatter(mca_df.fs_c()[:, 0],mca_df.fs_c()[:, 1],c=col)
for i, j, nom in zip(mca_df.fs_c()[:, 0],mca_df.fs_c()[:, 1], dc.columns):
       plt.text(i, j, nom)
plt.show()

Comme pour l'ACP et au contraire de R (cf. FactoMineR), les librairies Python sont pauvres en fonctions graphiques directement adaptées à l'AFCM. Le graphique est construit à partir des fonctions de MatPlotLib. Remarquer l'évidente redondance entre la variable Prix et celle Classe.

Q Tenter une interprétation des correspondances entre les modalités. Il serait opportun d'en déclarer une supplémentaire; cela semble possible dans la fonction MCA mais n'est pas documenté.