Importation et préparation des données¶

In [ ]:
#version 3.10 de Python min.
import sys
print(sys.version)
3.10.10 | packaged by conda-forge | (main, Mar 24 2023, 20:00:38) [MSC v.1934 64 bit (AMD64)]
In [ ]:
#changement de dossier
import os
os.chdir("C:/Users/ricco/Desktop/demo")

#importation de la matrice sous forme de data frame
#colonne 0 et ligne 0 = etiquettes
import pandas
dfAdj = pandas.read_excel("matrice_adjacence_iut_bis.xlsx",header=0,index_col=0)
dfAdj.head()
Out[ ]:
BEN BES BOU BRU CAM CHU DUC LAN LEX MAR ... CAL DIF FIR FRE FUM HAD HEL MZA VER VID
IUT
BEN 0 0 1 0 0 0 0 0 1 0 ... 0 0 0 0 0 0 0 1 0 0
BES 0 0 0 1 1 1 1 0 0 0 ... 0 0 0 0 0 0 0 0 0 0
BOU 1 0 0 0 0 0 0 0 0 1 ... 0 0 0 0 1 0 0 1 0 0
BRU 0 1 0 0 1 1 0 1 1 0 ... 0 1 1 1 0 0 1 0 1 0
CAM 0 1 0 1 0 1 0 0 0 0 ... 0 1 1 1 0 0 0 0 1 0

5 rows × 24 columns

In [ ]:
#tranformation matrice de distances cosinus
from sklearn.metrics.pairwise import cosine_distances
D = cosine_distances(dfAdj)

#transformer en data frame
D = pandas.DataFrame(D,index = dfAdj.index, columns = dfAdj.columns)

#premières valeurs
print(D.iloc[:5,:5])
          BEN       BES       BOU       BRU       CAM
IUT                                                  
BEN  0.000000  1.000000  0.795876  0.849244  1.000000
BES  1.000000  0.000000  1.000000  0.698489  0.622036
BOU  0.795876  1.000000  0.000000  0.876909  1.000000
BRU  0.849244  0.698489  0.876909  0.000000  0.316237
CAM  1.000000  0.622036  1.000000  0.316237  0.000000
In [ ]:
#vérifier s'il s'agit bien du matrice de distance
#symétrie, positivité, inégalité triangulaire
import scipy
print(scipy.spatial.distance.is_valid_dm(D))
True

Positionnement multidimensionnel¶

In [ ]:
#importation des procédures et fonctions de calcul
#version 0.0.5 de "scientistiools" pour cette démo
from scientisttools.extractfactor import get_mds,get_eig
from scientisttools.manifold import CMDSCALE

#librairie pour des graphiques performants
from scientisttools.ggplot import fviz_cmds
In [ ]:
#documentation de cmdscale
help(CMDSCALE)
Help on class CMDSCALE in module scientisttools.manifold:

class CMDSCALE(sklearn.base.BaseEstimator, sklearn.base.TransformerMixin)
 |  CMDSCALE(n_components=None, labels=None, sup_labels=None, proximity='euclidean', normalized_stress=True, graph=True, figsize=None)
 |  
 |  Classic Muldimensional Scaling (CMDSCALE)
 |  
 |  This is a classical multidimensional scaling also 
 |  known as Principal Coordinates Analysis (PCoA).
 |  
 |  Performs Classical Multidimensional Scaling (MDS) with supplementary 
 |  rows points.
 |  
 |  Parameters
 |  ----------
 |  n_components : int, default=None
 |      Number of dimensions in which to immerse the dissimilarities.
 |  
 |  labels : list of string,   default : None
 |      Labels for the rows.
 |  
 |  sup_labels : list of string, default = None
 |      Labels of supplementary rows.
 |  
 |  proximity :  {'euclidean','precomputed','similarity'}, default = 'euclidean'
 |      Dissmilarity measure to use :
 |      - 'euclidean':
 |          Pairwise Euclidean distances between points in the dataset
 |      
 |      - 'precomputed':
 |          Pre-computed dissimilarities are passed disrectly to ``fit`` and ``fit_transform``.
 |      
 |      - `similarity`:
 |          Similarity matrix is transform to dissimilarity matrix before passed to ``fit`` and ``fit_transform``.
 |  
 |  normalized_stress : bool, default = True
 |      Whether use and return normed stress value (Stress-1) instead of raw
 |      stress calculated by default.
 |  
 |  graph : bool, default = True
 |      if True a graph is displayed
 |  
 |  figsize : tuple of int, default = None
 |      Width, height in inches.
 |  
 |  Returns
 |  -------
 |  n_components_ : int
 |      The estimated number of components.
 |  
 |  labels_ : array of strings
 |      Labels for the rows.
 |  
 |  nobs_ : int
 |      number of rows
 |  
 |  dist_ : ndarray of shape -n_rows, nr_ows)
 |      Eulidean distances matrix.
 |      
 |  eig_ : array of float
 |      A 4 x n_components_ matrix containing all the eigenvalues
 |      (1st row), difference (2nd row) the percentage of variance (3rd row) and the
 |      cumulative percentage of variance (4th row).
 |  
 |  eigen_vector_ : array of float:
 |      A matrix containing eigenvectors
 |  
 |  coord_ : ndarray of shape (n_rows,n_components_)
 |      A n_rows x n_components_ matrix containing the row coordinates.
 |  
 |  res_dist_ : ndarray of shape (n_rows,n_rows_)
 |      A n_rows x n_rows_ matrix containing the distances based on coordinates.
 |  
 |  stress_ : float
 |  
 |  inertia_ : 
 |  
 |  dim_index_ : 
 |  
 |  centered_matrix_ : ndarray of shape
 |  
 |  model_ : string
 |      The model fitted = 'cmds'
 |  
 |  Method resolution order:
 |      CMDSCALE
 |      sklearn.base.BaseEstimator
 |      sklearn.base.TransformerMixin
 |      sklearn.utils._set_output._SetOutputMixin
 |      builtins.object
 |  
 |  Methods defined here:
 |  
 |  __init__(self, n_components=None, labels=None, sup_labels=None, proximity='euclidean', normalized_stress=True, graph=True, figsize=None)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  fit(self, X, y=None)
 |      Fit the model to X
 |      
 |      Parameters
 |      ----------
 |      X : DataFrame of float, shape (n_rows, n_columns)
 |      
 |      y : None
 |          y is ignored
 |      
 |      Returns:
 |      --------
 |      self : object
 |              Returns the instance itself
 |  
 |  fit_transform(self, X, y=None)
 |      Fit the model with X and apply the dimensionality reduction on X.
 |      
 |      Parameters
 |      ----------
 |      X : pd.DataFrame, shape (n_samples, n_features)
 |          New data, where n_samples in the number of samples
 |          and n_features is the number of features.
 |      
 |      Returns
 |      -------
 |      X_new : array-like, shape (n_samples, n_components)
 |  
 |  transform(self, X, y=None)
 |      Apply the Multidimensional Scaling reduction on X
 |      
 |      X is projected on the first axes previous extracted from a training set.
 |      
 |      Parameters
 |      ----------
 |      X : DataFrame of float, shape (n_rows_sup, n_columns)
 |          New data, where n_row_sup is the number of supplementary
 |          row points and n_columns is the number of columns
 |          X rows correspond to supplementary row points that are 
 |          projected on the axes
 |          X is a table containing numeric values
 |      
 |      y : None
 |          y is ignored
 |      
 |      Returns
 |      -------
 |      X_new : DataFrame of float, shape (n_rows_sup, n_components_)
 |              X_new : coordinates of the projections of the supplementary
 |              row points on the axes.
 |  
 |  ----------------------------------------------------------------------
 |  Methods inherited from sklearn.base.BaseEstimator:
 |  
 |  __getstate__(self)
 |  
 |  __repr__(self, N_CHAR_MAX=700)
 |      Return repr(self).
 |  
 |  __setstate__(self, state)
 |  
 |  get_params(self, deep=True)
 |      Get parameters for this estimator.
 |      
 |      Parameters
 |      ----------
 |      deep : bool, default=True
 |          If True, will return the parameters for this estimator and
 |          contained subobjects that are estimators.
 |      
 |      Returns
 |      -------
 |      params : dict
 |          Parameter names mapped to their values.
 |  
 |  set_params(self, **params)
 |      Set the parameters of this estimator.
 |      
 |      The method works on simple estimators as well as on nested objects
 |      (such as :class:`~sklearn.pipeline.Pipeline`). The latter have
 |      parameters of the form ``<component>__<parameter>`` so that it's
 |      possible to update each component of a nested object.
 |      
 |      Parameters
 |      ----------
 |      **params : dict
 |          Estimator parameters.
 |      
 |      Returns
 |      -------
 |      self : estimator instance
 |          Estimator instance.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from sklearn.base.BaseEstimator:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
 |  
 |  ----------------------------------------------------------------------
 |  Methods inherited from sklearn.utils._set_output._SetOutputMixin:
 |  
 |  set_output(self, *, transform=None)
 |      Set output container.
 |      
 |      See :ref:`sphx_glr_auto_examples_miscellaneous_plot_set_output.py`
 |      for an example on how to use the API.
 |      
 |      Parameters
 |      ----------
 |      transform : {"default", "pandas"}, default=None
 |          Configure output of `transform` and `fit_transform`.
 |      
 |          - `"default"`: Default output format of a transformer
 |          - `"pandas"`: DataFrame output
 |          - `None`: Transform configuration is unchanged
 |      
 |      Returns
 |      -------
 |      self : estimator instance
 |          Estimator instance.
 |  
 |  ----------------------------------------------------------------------
 |  Class methods inherited from sklearn.utils._set_output._SetOutputMixin:
 |  
 |  __init_subclass__(auto_wrap_output_keys=('transform',), **kwargs) from builtins.type
 |      This method is called when a class is subclassed.
 |      
 |      The default implementation does nothing. It may be
 |      overridden to extend subclasses.

In [ ]:
#MDS classique
mds = CMDSCALE(n_components=2,
                  labels = dfAdj.index,
                  proximity="precomputed",
                  graph=False)
mds.fit(D)
Out[ ]:
CMDSCALE(graph=False,
         labels=Index(['BEN', 'BES', 'BOU', 'BRU', 'CAM', 'CHU', 'DUC', 'LAN', 'LEX', 'MAR',
       'ROG', 'TOS', 'BAR', 'BEL', 'CAL', 'DIF', 'FIR', 'FRE', 'FUM', 'HAD',
       'HEL', 'MZA', 'VER', 'VID'],
      dtype='object', name='IUT'),
         n_components=2, proximity='precomputed')
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
CMDSCALE(graph=False,
         labels=Index(['BEN', 'BES', 'BOU', 'BRU', 'CAM', 'CHU', 'DUC', 'LAN', 'LEX', 'MAR',
       'ROG', 'TOS', 'BAR', 'BEL', 'CAL', 'DIF', 'FIR', 'FRE', 'FUM', 'HAD',
       'HEL', 'MZA', 'VER', 'VID'],
      dtype='object', name='IUT'),
         n_components=2, proximity='precomputed')
In [ ]:
#valeurs propres
eig = get_eig(mds)
print(eig)
       eigenvalue  difference  proportion  cumulative
Dim.1    3.454896    2.380006   49.896707   49.896707
Dim.2    1.074890    0.130283   15.523906   65.420614
In [ ]:
#coordonnées dans le repère
coord = get_mds(mds)['coord']
coord
Out[ ]:
Dim.1 Dim.2
IUT
BEN -0.340080 -0.333392
BES 0.279570 0.261165
BOU -0.438907 -0.087061
BRU 0.318793 0.060490
CAM 0.449507 0.060103
CHU 0.169649 0.343743
DUC 0.248624 0.346216
LAN 0.388840 -0.065955
LEX -0.024896 -0.177148
MAR -0.456017 -0.143914
ROG -0.205494 -0.507675
TOS -0.285100 0.336514
BAR 0.430237 -0.186521
BEL -0.294874 -0.079126
CAL -0.440374 0.294027
DIF 0.422357 -0.023914
FIR 0.368785 -0.120002
FRE 0.341507 -0.012157
FUM -0.505317 -0.038268
HAD -0.424753 0.179215
HEL 0.460057 -0.138931
MZA -0.440991 0.020706
VER 0.464717 -0.092120
VID -0.485839 0.104004
In [ ]:
#max
print(coord.max())

#min
print(coord.min())
Dim.1    0.464717
Dim.2    0.346216
dtype: float64
Dim.1   -0.505317
Dim.2   -0.507675
dtype: float64
In [ ]:
#graphique -- remarquer l'affectation pour garder en mémoire le graphique
import plotnine as pn
first_plot = fviz_cmds(mds,xlim=(-0.55,+0.55),ylim=(-0.55,+0.55),marker=' ',color='navy')
print(first_plot)

Graphique des individus avec les connexions¶

Puisqu'initialement, nous sommes partis d'une matrice d'adjacence, on doit pouvoir visualiser les connexions entre les individus.

In [ ]:
#lien entre amis
segments = []

#passer en revue la matrice d'adjacence
for i in range(0,dfAdj.shape[0]):
    for j in range(i+1,dfAdj.shape[1]):
        if (dfAdj.iloc[i,j] == 1):
            segments.append([coord.iloc[i,:].values,coord.iloc[j,:].values])

#nombre de segments
print(len(segments))
78
In [ ]:
#ex. coordoonnées du premier segment
#coordoonées des individus connectés
segments[0]
Out[ ]:
[array([-0.34007989, -0.33339164]), array([-0.43890719, -0.08706082])]
In [ ]:
#collection de lignes pour le graphique
#zorder = 1 pour que les lignes passent en dessous des cercles
from matplotlib.collections import LineCollection
lc = LineCollection(segments=segments,linewidth=1,color='silver',zorder=1)

#graphique des individus avec les connexions
import matplotlib.pyplot as plt
fig, axe = plt.subplots(figsize=(7,7))
axe.axis([-0.55,+0.55,-0.55,+0.55])
axe.plot([-0.55,+0.55],[0,0],color='gainsboro',linestyle='--')
axe.plot([0,0],[-0.55,+0.55],color='gainsboro',linestyle='--')
axe.set_xlabel("Dim.1")
axe.set_ylabel("Dim.2")
#ajouter la collection de lignes reliant les individus
axe.add_collection(lc)
#titre du graphique
plt.title("Positionnement multidimensionnel")
#ajouter les informations sur les individus
for i in range(coord.shape[0]):
    axe.add_artist(plt.Circle((coord.iloc[i,0],coord.iloc[i,1]),radius=0.03,
                              facecolor='beige',edgecolor='black',fill=True))
    axe.text(coord.iloc[i,0],coord.iloc[i,1],coord.index[i],
             color='blue',horizontalalignment='center',verticalalignment='center',fontsize=7)
plt.show()

Clustering K-Means¶

In [ ]:
#k-means avec 2 groupes
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=2,n_init=10,random_state=0)
kmeans.fit(coord)

#inertie
kmeans.inertia_
c:\Users\ricco\anaconda3\envs\env_sttools\lib\site-packages\sklearn\cluster\_kmeans.py:1382: UserWarning: KMeans is known to have a memory leak on Windows with MKL, when there are less chunks than available threads. You can avoid it by setting the environment variable OMP_NUM_THREADS=1.
Out[ ]:
1.3555752821158107
In [ ]:
#les groupes
import numpy
numpy.unique(kmeans.labels_,return_counts=True)
Out[ ]:
(array([0, 1]), array([12, 12], dtype=int64))
In [ ]:
#renommage des groupes pour plus de clarté
groupes = numpy.where(kmeans.labels_ == 0, "A", "B")
numpy.unique(groupes,return_counts=True)
Out[ ]:
(array(['A', 'B'], dtype='<U1'), array([12, 12], dtype=int64))
In [ ]:
#pour la légende
import matplotlib.patches as mpatches

#collection de lignes pour le graphique
lc = LineCollection(segments=segments,linewidth=1,color='silver',zorder=1)

#graphique des individus avec les connexions
fig, axe = plt.subplots(figsize=(7,7))
axe.axis([-0.55,+0.55,-0.55,+0.55])
axe.plot([-0.55,+0.55],[0,0],color='gainsboro',linestyle='--')
axe.plot([0,0],[-0.55,+0.55],color='gainsboro',linestyle='--')
axe.set_xlabel("Dim.1")
axe.set_ylabel("Dim.2")
axe.add_collection(lc)
plt.title("MDS et groupes d'appartenance (K-Means)")
#jeu de couleurs
couleurs = {'A':'palegreen','B':'coral'}
#ajouter
for i in range(coord.shape[0]):
    axe.add_artist(plt.Circle((coord.iloc[i,0],coord.iloc[i,1]),radius=0.03,
                              facecolor=couleurs[groupes[i]],edgecolor='black',fill=True))
    axe.text(coord.iloc[i,0],coord.iloc[i,1],coord.index[i],
             color='blue',horizontalalignment='center',verticalalignment='center',fontsize=7)

#legende -- indicateur de groupes
p1 = mpatches.Patch(color=couleurs['A'],label='Groupe A')
p2 = mpatches.Patch(color=couleurs['B'],label='Groupe B')
axe.legend(handles=[p1,p2],loc='lower right')

#affichage enfin
plt.show()
In [ ]:
#les amis de LEX
dfAdj.index[dfAdj.loc['LEX']==1]
Out[ ]:
Index(['BEN', 'BRU', 'LAN', 'MZA'], dtype='object', name='IUT')

Traitement d'un individu supplémentaire¶

In [ ]:
#chargement de l'individu
dfSupp = pandas.read_excel("matrice_adjacence_iut_bis.xlsx",header=0,index_col=0,sheet_name="SUPPLEMENTAIRE")
dfSupp.transpose()
Out[ ]:
IUT BEN BES BOU BRU CAM CHU DUC LAN LEX MAR ... CAL DIF FIR FRE FUM HAD HEL MZA VER VID
ROS 0 1 0 1 1 1 1 0 0 0 ... 0 0 0 0 0 1 1 0 0 0

1 rows × 24 columns

Individus supplémentaire dans le repère MDS¶

In [ ]:
#calculer la distance avec les individus actifs
dist_supp = cosine_distances(dfAdj,dfSupp.transpose())
print(dist_supp)
[[1.        ]
 [0.24407105]
 [1.        ]
 [0.54415769]
 [0.57142857]
 [0.15484575]
 [0.56356422]
 [0.83096915]
 [0.81101776]
 [1.        ]
 [1.        ]
 [0.85714286]
 [0.83096915]
 [0.76095428]
 [0.83096915]
 [0.59910814]
 [0.52190856]
 [0.62203553]
 [0.86636938]
 [0.85714286]
 [0.84569665]
 [0.87401184]
 [0.59910814]
 [0.84569665]]
In [ ]:
#transformer en data frame et transposition
df_dist_supp = pandas.DataFrame(numpy.transpose(dist_supp),index=['ROS'],columns=dfAdj.columns)
print(df_dist_supp)
     BEN       BES  BOU       BRU       CAM       CHU       DUC       LAN   
ROS  1.0  0.244071  1.0  0.544158  0.571429  0.154846  0.563564  0.830969  \

          LEX  MAR  ...       CAL       DIF       FIR       FRE       FUM   
ROS  0.811018  1.0  ...  0.830969  0.599108  0.521909  0.622036  0.866369  \

          HAD       HEL       MZA       VER       VID  
ROS  0.857143  0.845697  0.874012  0.599108  0.845697  

[1 rows x 24 columns]
In [ ]:
#coordonnées dans le repère "factoriel"
coord_supp = mds.transform(df_dist_supp)[0]

#transformer en numpy
coord_supp = numpy.asarray(coord_supp)
print(coord_supp)
[0.23383132 0.37437213]
In [ ]:
#second graphique
#positionner l'individu supplémentaire dans l'espace factoriel
second_plot = first_plot + pn.geom_text(x = coord_supp[0],y=coord_supp[1],label="ROS",color="green")
print(second_plot)

Croisement avec les groupes¶

In [ ]:
#nombre d'amis de ROS
dfSupp.ROS.sum()
Out[ ]:
7
In [ ]:
#les amis de ROS
print(dfSupp.index[dfSupp.ROS==1])
Index(['BES', 'BRU', 'CAM', 'CHU', 'DUC', 'HAD', 'HEL'], dtype='object', name='IUT')
In [ ]:
#amis selon les groupes
pandas.crosstab(dfSupp.ROS,groupes).loc[1]
Out[ ]:
col_0
A    6
B    1
Name: 1, dtype: int64
In [ ]:
#liste des amis de ROS du groupe "A"
dfSupp.index[(groupes == 'A') & (dfSupp.ROS == 1)]
Out[ ]:
Index(['BES', 'BRU', 'CAM', 'CHU', 'DUC', 'HEL'], dtype='object', name='IUT')
In [ ]:
#liste des amis de ROS du groupe "B"
dfSupp.index[(groupes == 'B') & (dfSupp.ROS == 1)]
Out[ ]:
Index(['HAD'], dtype='object', name='IUT')
In [ ]:
#segments des connexions associés à ROS
segments_supp = []

#passer en revue ses amis
for i in range(dfSupp.ROS.shape[0]):
    if (dfSupp.ROS[i] == 1):
        segments_supp.append([coord_supp,coord.iloc[i,:].values])
                             
#affichage
print(segments)
[[array([-0.34007989, -0.33339164]), array([-0.43890719, -0.08706082])], [array([-0.34007989, -0.33339164]), array([-0.02489612, -0.17714792])], [array([-0.34007989, -0.33339164]), array([-0.28509989,  0.3365138 ])], [array([-0.34007989, -0.33339164]), array([-0.44099081,  0.02070603])], [array([0.2795699 , 0.26116541]), array([0.31879347, 0.06049046])], [array([0.2795699 , 0.26116541]), array([0.44950743, 0.06010262])], [array([0.2795699 , 0.26116541]), array([0.16964875, 0.34374341])], [array([0.2795699 , 0.26116541]), array([0.24862429, 0.34621586])], [array([-0.43890719, -0.08706082]), array([-0.45601715, -0.14391411])], [array([-0.43890719, -0.08706082]), array([-0.20549411, -0.50767516])], [array([-0.43890719, -0.08706082]), array([-0.29487361, -0.07912574])], [array([-0.43890719, -0.08706082]), array([-0.50531679, -0.03826818])], [array([-0.43890719, -0.08706082]), array([-0.44099081,  0.02070603])], [array([0.31879347, 0.06049046]), array([0.44950743, 0.06010262])], [array([0.31879347, 0.06049046]), array([0.16964875, 0.34374341])], [array([0.31879347, 0.06049046]), array([ 0.38883962, -0.06595502])], [array([0.31879347, 0.06049046]), array([-0.02489612, -0.17714792])], [array([0.31879347, 0.06049046]), array([-0.29487361, -0.07912574])], [array([0.31879347, 0.06049046]), array([ 0.42235662, -0.0239138 ])], [array([0.31879347, 0.06049046]), array([ 0.3687848 , -0.12000172])], [array([0.31879347, 0.06049046]), array([ 0.34150654, -0.01215702])], [array([0.31879347, 0.06049046]), array([ 0.46005663, -0.13893149])], [array([0.31879347, 0.06049046]), array([ 0.46471668, -0.09211977])], [array([0.44950743, 0.06010262]), array([0.16964875, 0.34374341])], [array([0.44950743, 0.06010262]), array([ 0.42235662, -0.0239138 ])], [array([0.44950743, 0.06010262]), array([ 0.3687848 , -0.12000172])], [array([0.44950743, 0.06010262]), array([ 0.34150654, -0.01215702])], [array([0.44950743, 0.06010262]), array([ 0.46471668, -0.09211977])], [array([0.16964875, 0.34374341]), array([0.24862429, 0.34621586])], [array([0.16964875, 0.34374341]), array([-0.42475284,  0.1792151 ])], [array([0.24862429, 0.34621586]), array([ 0.3687848 , -0.12000172])], [array([ 0.38883962, -0.06595502]), array([-0.02489612, -0.17714792])], [array([ 0.38883962, -0.06595502]), array([ 0.3687848 , -0.12000172])], [array([ 0.38883962, -0.06595502]), array([ 0.34150654, -0.01215702])], [array([ 0.38883962, -0.06595502]), array([ 0.46471668, -0.09211977])], [array([-0.02489612, -0.17714792]), array([-0.44099081,  0.02070603])], [array([-0.45601715, -0.14391411]), array([-0.20549411, -0.50767516])], [array([-0.45601715, -0.14391411]), array([-0.29487361, -0.07912574])], [array([-0.45601715, -0.14391411]), array([-0.50531679, -0.03826818])], [array([-0.45601715, -0.14391411]), array([-0.44099081,  0.02070603])], [array([-0.20549411, -0.50767516]), array([ 0.42235662, -0.0239138 ])], [array([-0.20549411, -0.50767516]), array([-0.44099081,  0.02070603])], [array([-0.28509989,  0.3365138 ]), array([-0.29487361, -0.07912574])], [array([-0.28509989,  0.3365138 ]), array([-0.44037432,  0.2940265 ])], [array([-0.28509989,  0.3365138 ]), array([ 0.3687848 , -0.12000172])], [array([-0.28509989,  0.3365138 ]), array([-0.50531679, -0.03826818])], [array([-0.28509989,  0.3365138 ]), array([-0.42475284,  0.1792151 ])], [array([-0.28509989,  0.3365138 ]), array([-0.48583907,  0.10400376])], [array([ 0.43023705, -0.18652058]), array([ 0.42235662, -0.0239138 ])], [array([ 0.43023705, -0.18652058]), array([ 0.3687848 , -0.12000172])], [array([ 0.43023705, -0.18652058]), array([ 0.34150654, -0.01215702])], [array([ 0.43023705, -0.18652058]), array([ 0.46005663, -0.13893149])], [array([ 0.43023705, -0.18652058]), array([ 0.46471668, -0.09211977])], [array([-0.29487361, -0.07912574]), array([-0.44037432,  0.2940265 ])], [array([-0.29487361, -0.07912574]), array([ 0.34150654, -0.01215702])], [array([-0.29487361, -0.07912574]), array([-0.50531679, -0.03826818])], [array([-0.29487361, -0.07912574]), array([-0.42475284,  0.1792151 ])], [array([-0.29487361, -0.07912574]), array([-0.44099081,  0.02070603])], [array([-0.29487361, -0.07912574]), array([-0.48583907,  0.10400376])], [array([-0.44037432,  0.2940265 ]), array([-0.50531679, -0.03826818])], [array([-0.44037432,  0.2940265 ]), array([-0.42475284,  0.1792151 ])], [array([-0.44037432,  0.2940265 ]), array([-0.48583907,  0.10400376])], [array([ 0.42235662, -0.0239138 ]), array([ 0.3687848 , -0.12000172])], [array([ 0.42235662, -0.0239138 ]), array([ 0.34150654, -0.01215702])], [array([ 0.42235662, -0.0239138 ]), array([ 0.46005663, -0.13893149])], [array([ 0.42235662, -0.0239138 ]), array([ 0.46471668, -0.09211977])], [array([ 0.3687848 , -0.12000172]), array([ 0.34150654, -0.01215702])], [array([ 0.3687848 , -0.12000172]), array([ 0.46005663, -0.13893149])], [array([ 0.3687848 , -0.12000172]), array([ 0.46471668, -0.09211977])], [array([ 0.34150654, -0.01215702]), array([ 0.46005663, -0.13893149])], [array([ 0.34150654, -0.01215702]), array([ 0.46471668, -0.09211977])], [array([-0.50531679, -0.03826818]), array([-0.42475284,  0.1792151 ])], [array([-0.50531679, -0.03826818]), array([-0.44099081,  0.02070603])], [array([-0.50531679, -0.03826818]), array([-0.48583907,  0.10400376])], [array([-0.42475284,  0.1792151 ]), array([-0.44099081,  0.02070603])], [array([-0.42475284,  0.1792151 ]), array([-0.48583907,  0.10400376])], [array([ 0.46005663, -0.13893149]), array([ 0.46471668, -0.09211977])], [array([-0.44099081,  0.02070603]), array([-0.48583907,  0.10400376])]]
In [ ]:
#illustration dans l'espace factoriel avec les groupes d'appartenance
#collection de lignes pour le graphique
lc = LineCollection(segments=segments_supp,linewidth=1,color='gray',zorder=0)

#graphique des individus avec les connexions
fig, axe = plt.subplots(figsize=(7,7))
axe.axis([-0.55,+0.55,-0.55,+0.55])
axe.plot([-0.55,+0.55],[0,0],color='gainsboro',linestyle='--')
axe.plot([0,0],[-0.55,+0.55],color='gainsboro',linestyle='--')
axe.set_xlabel("Dim.1")
axe.set_ylabel("Dim.2")
plt.title("MDS - Groupes d'appartenance et indiv. supp.")
#jeu de couleurs
couleurs = {'A':'palegreen','B':'coral'}
#ajouter les individus actifs
for i in range(coord.shape[0]):
    axe.add_artist(plt.Circle((coord.iloc[i,0],coord.iloc[i,1]),radius=0.03,
                              facecolor=couleurs[groupes[i]],edgecolor='black',fill=True))
    axe.text(coord.iloc[i,0],coord.iloc[i,1],coord.index[i],
             color='blue',horizontalalignment='center',verticalalignment='center',fontsize=7)
#ajouter l'individu illustratif
axe.add_artist(plt.Circle((coord_supp[0],coord_supp[1]),radius=0.03,
                              facecolor='khaki',edgecolor='black',fill=True))
axe.text(coord_supp[0],coord_supp[1],'ROS',
             color='darkgreen',horizontalalignment='center',verticalalignment='center',fontsize=7,fontweight=1000)
#ajouter enfin les connexions avec l'individu illustratif
axe.add_collection(lc)
#legende -- indicateur de groupes
p1 = mpatches.Patch(color=couleurs['A'],label='Groupe A')
p2 = mpatches.Patch(color=couleurs['B'],label='Groupe B')
axe.legend(handles=[p1,p2],loc='lower right')

#affichage enfin
plt.show()