Mise en place
1a. Import librairies
1b. Fonctions
1c. Import des données
1d. Archivage des concurrents
1e. Archivage des outliers
1f. Essai avec score
Analyses descriptives univariées
Analyses descriptives bivariées
Analyse des Composantes Principales (ACP)
4a. Préparation des données
i. Séparation des données
ii. Standardisation des données
iii. Réduction des dimensions
4b. Analyse de l'ACP
i. Choix des composantes principales
ii. Qualité de représentation des variables (cos2)
iii. Visualisation & Interprétation
Classification Ascendante Hiérarchique (CAH)
5a. Préparation des données
i. Séparation des données
ii. Standardisation des données
5b. Clustering
i. Linkage
ii. Dendrogram
iii. Clusters
Kmeans
Kmeans sur F1 & F2
Comparaison des listes de pays intéressant pour l'exportation de volaille
Profils du cluster gardé
9a. PCA sur données des pays concernés du cluster sélectionné
9b. Kmeans sur les pays sélectionnés
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from math import *
import plotly.graph_objects as go
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import AgglomerativeClustering
from sklearn import preprocessing
from sklearn.cluster import KMeans
from scipy.cluster.hierarchy import dendrogram, linkage
import warnings
warnings.filterwarnings("ignore")
warnings.warn("DelftStack")
warnings.warn("Do not show this message")
def show_outliers_str(df, colonne):
"""
Crée une boucle qui vient afficher sur un graphique les pays avec des valeurs atypiques
Prérequis :
- 1 dataframe avec la variable Zone + 1 variables quantitative minimum
"""
#Cibler les outliers
Q1 = df[colonne].quantile(0.25)
Q3 = df[colonne].quantile(0.75)
IQR = Q3-Q1
out_inf = Q1 - (IQR * 1.5)
out_sup = Q3 + (IQR * 1.5)
zone_outlier = df.loc[(df[colonne] < out_inf) | (df[colonne] > out_sup)]["Zone"].tolist()
y_outlier = df.loc[(df[colonne] < out_inf) | (df[colonne] > out_sup)][colonne].tolist()
#Affichage zones outliers
for zone in range(len(zone_outlier)):
plt.text(x=0.1, s=zone_outlier[zone], y=y_outlier[zone])
def correlation_graph(pca,
x_y,
features) :
"""Affiche le graphe des correlations
Positional arguments :
-----------------------------------
pca : sklearn.decomposition.PCA : notre objet PCA qui a été fit
x_y : list ou tuple : le couple x,y des plans à afficher, exemple [0,1] pour F1, F2
features : list ou tuple : la liste des features (ie des dimensions) à représenter
"""
# Extrait x et y
x,y=x_y
# Taille de l'image (en inches)
fig, ax = plt.subplots(figsize=(10, 9))
# Pour chaque composante :
for i in range(0, pca.components_.shape[1]):
# Les flèches
ax.arrow(0,0,
pca.components_[x, i],
pca.components_[y, i],
head_width=0.07,
head_length=0.07,
width=0.02, )
# Les labels
plt.text(pca.components_[x, i] + 0.05,
pca.components_[y, i] + 0.05,
features[i])
# Affichage des lignes horizontales et verticales
plt.plot([-1, 1], [0, 0], color='grey', ls='--')
plt.plot([0, 0], [-1, 1], color='grey', ls='--')
# Nom des axes, avec le pourcentage d'inertie expliqué
plt.xlabel('F{} ({}%)'.format(x+1, round(100*pca.explained_variance_ratio_[x],1)))
plt.ylabel('F{} ({}%)'.format(y+1, round(100*pca.explained_variance_ratio_[y],1)))
plt.title("Cercle des corrélations (F{} et F{})".format(x+1, y+1))
# Le cercle
an = np.linspace(0, 2 * np.pi, 100)
plt.plot(np.cos(an), np.sin(an)) # Add a unit circle for scale
# Axes et display
plt.axis('equal')
#plt.show(block=False)
def display_factorial_planes( X_projected,
x_y,
pca=None,
labels = None,
clusters=None,
alpha=1,
figsize=[10,8],
marker="." ):
"""
Affiche la projection des individus
Positional arguments :
-------------------------------------
X_projected : np.array, pd.DataFrame, list of list : la matrice des points projetés
x_y : list ou tuple : le couple x,y des plans à afficher, exemple [0,1] pour F1, F2
Optional arguments :
-------------------------------------
pca : sklearn.decomposition.PCA : un objet PCA qui a été fit, cela nous permettra d'afficher la variance de chaque composante, default = None
labels : list ou tuple : les labels des individus à projeter, default = None
clusters : list ou tuple : la liste des clusters auquel appartient chaque individu, default = None
alpha : float in [0,1] : paramètre de transparence, 0=100% transparent, 1=0% transparent, default = 1
figsize : list ou tuple : couple width, height qui définit la taille de la figure en inches, default = [10,8]
marker : str : le type de marker utilisé pour représenter les individus, points croix etc etc, default = "."
"""
# Transforme X_projected en np.array
X_ = np.array(X_projected)
# On définit la forme de la figure si elle n'a pas été donnée
if not figsize:
figsize = (7,6)
# On gère les labels
if labels is None :
labels = []
try :
len(labels)
except Exception as e :
raise e
# On vérifie la variable axis
if not len(x_y) ==2 :
raise AttributeError("2 axes sont demandées")
if max(x_y )>= X_.shape[1] :
raise AttributeError("la variable axis n'est pas bonne")
# on définit x et y
x, y = x_y
# Initialisation de la figure
fig, ax = plt.subplots(1, 1, figsize=figsize)
# On vérifie s'il y a des clusters ou non
c = None if clusters is None else clusters
# Les points
# plt.scatter( X_[:, x], X_[:, y], alpha=alpha,
# c=c, cmap="Set1", marker=marker)
sns.scatterplot(data=None, x=X_[:, x], y=X_[:, y], hue=c)
# Si la variable pca a été fournie, on peut calculer le % de variance de chaque axe
if pca :
v1 = str(round(100*pca.explained_variance_ratio_[x])) + " %"
v2 = str(round(100*pca.explained_variance_ratio_[y])) + " %"
else :
v1=v2= ''
# Nom des axes, avec le pourcentage d'inertie expliqué
ax.set_xlabel(f'F{x+1} {v1}')
ax.set_ylabel(f'F{y+1} {v2}')
# Valeur x max et y max
x_max = np.abs(X_[:, x]).max() *1.1
y_max = np.abs(X_[:, y]).max() *1.1
# On borne x et y
ax.set_xlim(left=-x_max, right=x_max)
ax.set_ylim(bottom= -y_max, top=y_max)
# Affichage des lignes horizontales et verticales
plt.plot([-x_max, x_max], [0, 0], color='grey', alpha=0.8)
plt.plot([0,0], [-y_max, y_max], color='grey', alpha=0.8)
# Affichage des labels des points
if len(labels) :
for i,(_x,_y) in enumerate(X_[:,[x,y]]):
plt.text(_x, _y+0.05, labels[i], fontsize='14', ha='center',va='center')
# Titre et display
plt.title(f"Projection des individus (sur F{x+1} et F{y+1})")
#plt.show()
def make_spider( df, row, title, color):
"""
À utiliser avec cette boucle pour afficher un graphique pour chaque ligne (cluster):
for row in range(0, len(df.index)):
make_spider( row=row, title='Cluster '+df['Cluster'][row], color=my_palette(row))
"""
my_dpi=100
plt.figure(figsize=(1700/my_dpi, 1700/my_dpi), dpi=my_dpi)
# number of variable
categories=list(df)[1:]
N = len(categories)
# What will be the angle of each axis in the plot? (we divide the plot / number of variable)
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1]
# Initialise the spider plot
ax = plt.subplot(5,2,row+1, polar=True, )
plt.subplots_adjust(hspace=0.8)
#Go through labels and adjust alignment based on where it is in the circle.
for label, angle in zip(ax.get_xticklabels(), angles):
if angle in (0, np.pi) :
label.set_horizontalalignment('center')
elif 0 < angle < np.pi :
label.set_horizontalalignment('left')
else :
label.set_horizontalalignment('right')
# If you want the first axis to be on top:
ax.set_theta_offset(pi / 2)
ax.set_theta_direction(-1)
# Draw one axe per variable + add labels labels yet
plt.xticks(angles[:-1], categories, color='grey', size=8)
# Draw ylabels
ax.set_rlabel_position(0)
plt.yticks([-2,-1,0,1,2], color="grey", size=12)
plt.ylim(-3, 3)
# Ind1
values=df.loc[row].drop('Cluster').values.flatten().tolist()
values += values[:1]
ax.plot(angles, values, color=color, linewidth=2, linestyle='solid')
ax.fill(angles, values, color=color, alpha=0.4)
# Add a title
plt.title(title, size=18, color=color, y=1.2)
df_original = pd.read_csv("database/BDD.csv")
df_original
Zone | Ratio volaille/carne en % | Variation cumulée - Proportion de volaille vs total viande | Disponibilité volaille (kg/personne/an) | exportation / production en % | Stabilite politique | Variation cumulée - PIB | Variation cumulée - Taux de change en % | PIB | Tarif EAV en % | MNT | Distance | Cas maladie recense | Statut | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Afghanistan | 22.222222 | 0.000000 | 2.0 | 0.000000 | -2.80 | -27.660894 | 21.313925 | 2096.1 | 5.0 | 0.0 | 5490.0 | 1.0 | Pays moins avancé (PMA) |
1 | Afrique du Sud | 58.730159 | 5.519604 | 37.0 | 3.783784 | -0.28 | -4.577614 | 10.836361 | 13950.5 | 0.0 | 39.0 | 8751.0 | 378.0 | Pays moins avancé (PMA) |
2 | Albanie | 27.906977 | 51.602564 | 12.0 | 0.000000 | 0.38 | 13.666119 | -13.081201 | 12771.0 | 10.0 | 0.0 | 1461.0 | 9.0 | En developpement |
3 | Algérie | 35.000000 | -4.761905 | 7.0 | 0.000000 | -0.92 | -6.517634 | 21.708918 | 11809.5 | 30.0 | 0.0 | 1158.0 | 7.0 | En developpement |
4 | Allemagne | 22.222222 | 5.194805 | 18.0 | 42.668428 | 0.59 | 0.203876 | -4.486119 | 53071.5 | 0.0 | 93.0 | 682.0 | 2031.0 | Développé |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
171 | Uruguay | 15.000000 | 143.386243 | 9.0 | 9.090909 | 1.05 | -1.325572 | 51.882994 | 23107.0 | 10.0 | 12.0 | 10772.0 | 17.0 | En developpement |
172 | Vanuatu | 40.000000 | 22.093023 | 16.0 | 0.000000 | 0.70 | -8.188176 | 1.513313 | 3031.2 | 20.0 | 0.0 | 16440.0 | 0.0 | En developpement |
173 | Viet Nam | 23.809524 | 61.538462 | 10.0 | 0.915332 | 0.23 | 17.429591 | 3.530142 | 9050.7 | 25.4 | 0.0 | 9869.0 | 551.0 | En developpement |
174 | Zambie | 15.000000 | 11.111111 | 3.0 | 2.040816 | 0.15 | -4.673833 | 110.289234 | 3395.5 | 40.0 | 0.0 | 7221.0 | 0.0 | Pays moins avancé (PMA) |
175 | Zimbabwe | 9.615385 | 30.000000 | 5.0 | 0.000000 | -0.71 | -9.293250 | 0.000000 | 2331.8 | 102.6 | 11.0 | 7760.0 | 0.0 | Pays moins avancé (PMA) |
176 rows × 14 columns
#Archivage
df_archive = df_original.loc[df_original["Zone"] == "Chine - RAS de Hong-Kong"]
#Suppression d'abord de la Chine (HK) du dataframe original pour ne pas impacter la moyenne et l'ecart-type
to_drop = df_original.loc[df_original["Zone"] == "Chine - RAS de Hong-Kong"].index.tolist()
df_original.drop(index=to_drop, inplace=True)
#Essai sans concurrent
ratio_export_moy = df_original["exportation / production en %"].mean()
ratio_export_moy_marge = df_original["exportation / production en %"].std()
ratio_export_marge = ratio_export_moy + ratio_export_moy_marge
#Archivage
df_archive = pd.concat([df_archive, df_original.loc[df_original["exportation / production en %"] > ratio_export_marge]])
#Suppression ou non des concurrents
to_drop = df_original.loc[df_original["exportation / production en %"] > ratio_export_marge].index.tolist()
df_original.drop(index=to_drop, inplace=True)
ratio_export_marge
42.42152276285621
#Variation cumulée - Taux de change > 3000 %
df_archive = pd.concat([df_archive, df_original.loc[df_original["Zone"] == "Soudan"]])
#Variation cumulée - Taux de change > 3000 %
drop_soudan = df_original.loc[df_original["Zone"] == "Soudan"].index.tolist()
df_original.drop(index=drop_soudan, inplace=True)
df_archive
Zone | Ratio volaille/carne en % | Variation cumulée - Proportion de volaille vs total viande | Disponibilité volaille (kg/personne/an) | exportation / production en % | Stabilite politique | Variation cumulée - PIB | Variation cumulée - Taux de change en % | PIB | Tarif EAV en % | MNT | Distance | Cas maladie recense | Statut | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
35 | Chine - RAS de Hong-Kong | 32.394366 | 22.632519 | 46.0 | 2766.666667 | 0.83 | 0.227097 | -0.256632 | 59842.2 | 0.0 | 20.0 | 9707.0 | 7.0 | Développé |
4 | Allemagne | 22.222222 | 5.194805 | 18.0 | 42.668428 | 0.59 | 0.203876 | -4.486119 | 53071.5 | 0.0 | 93.0 | 682.0 | 2031.0 | Développé |
11 | Autriche | 21.176471 | 5.628655 | 18.0 | 52.702703 | 1.05 | -0.095804 | -4.486119 | 54173.0 | 0.0 | 93.0 | 921.0 | 76.0 | Développé |
18 | Belgique | 20.000000 | 13.636364 | 11.0 | 141.684665 | 0.43 | 2.571651 | -4.486119 | 50442.3 | 0.0 | 93.0 | 379.0 | 374.0 | Développé |
45 | Danemark | 32.467532 | -17.577465 | 25.0 | 91.447368 | 0.87 | 4.707651 | -4.782455 | 55356.7 | 0.0 | 93.0 | 1151.0 | 374.0 | Développé |
50 | Émirats arabes unis | 61.363636 | -4.938272 | 27.0 | 56.140351 | 0.62 | -2.035054 | 0.000000 | 71182.4 | 5.0 | 114.0 | 5171.0 | 0.0 | Développé |
53 | Estonie | 33.870968 | -12.676056 | 21.0 | 55.000000 | 0.65 | 14.475236 | -4.486119 | 33821.9 | 0.0 | 93.0 | 2029.0 | 63.0 | Développé |
72 | Hongrie | 31.250000 | 1.463415 | 25.0 | 42.596349 | 0.81 | 13.871008 | 10.460646 | 29501.1 | 0.0 | 93.0 | 1234.0 | 746.0 | En developpement |
78 | Irlande | 31.578947 | 5.555556 | 24.0 | 63.698630 | 1.00 | 31.829009 | -4.486119 | 77749.2 | 0.0 | 93.0 | 949.0 | 146.0 | Développé |
91 | Lettonie | 30.434783 | 12.524462 | 21.0 | 60.606061 | 0.46 | 11.885149 | -4.486119 | 28673.6 | 0.0 | 93.0 | 1832.0 | 26.0 | En developpement |
95 | Lituanie | 35.000000 | -13.941480 | 28.0 | 50.746269 | 0.78 | 16.419988 | -4.486119 | 33761.9 | 0.0 | 93.0 | 1734.0 | 106.0 | Développé |
96 | Luxembourg | 22.352941 | -1.162791 | 19.0 | 50.746269 | 1.33 | 0.607030 | -4.486119 | 114986.0 | 0.0 | 93.0 | 384.0 | 9.0 | Développé |
97 | Macédoine du Nord | 50.000000 | -17.073171 | 20.0 | 50.000000 | -0.25 | 4.825391 | -4.689067 | 15706.5 | 0.0 | 0.0 | 1558.0 | 2.0 | En developpement |
113 | Namibie | 36.363636 | 1.315789 | 12.0 | 120.000000 | 0.63 | -11.586505 | 11.010186 | 10335.3 | 0.0 | 5.0 | 7755.0 | 7.0 | Pays moins avancé (PMA) |
121 | Oman | 47.826087 | -11.025145 | 22.0 | 283.333333 | 0.75 | 0.223272 | 0.000000 | 34218.4 | 5.0 | 64.0 | 5485.0 | 1.0 | En developpement |
128 | Pays-Bas (Royaume des) | 25.000000 | -25.000000 | 16.0 | 129.026388 | 0.92 | 2.775166 | -4.486119 | 55088.6 | 0.0 | 93.0 | 556.0 | 825.0 | Développé |
131 | Pologne | 37.931034 | -8.171604 | 33.0 | 44.086022 | 0.52 | 16.547778 | 2.185130 | 29958.1 | 0.0 | 93.0 | 1318.0 | 464.0 | Développé |
153 | Slovaquie | 23.728814 | -14.397321 | 14.0 | 47.887324 | 0.91 | 6.002342 | -4.486119 | 30061.6 | 0.0 | 93.0 | 1213.0 | 24.0 | Développé |
154 | Slovénie | 33.333333 | 22.950820 | 24.0 | 42.647059 | 0.87 | 9.666206 | -4.486119 | 36507.6 | 0.0 | 93.0 | 909.0 | 68.0 | Développé |
159 | Suriname | 72.727273 | 8.196721 | 32.0 | 50.000000 | 0.13 | -16.821851 | 143.582961 | 17753.1 | 40.0 | 3.0 | 7160.0 | 0.0 | En developpement |
163 | Thaïlande | 46.428571 | -5.230769 | 13.0 | 46.741045 | -0.75 | 0.405691 | -5.782936 | 17008.0 | 30.0 | 0.0 | 9470.0 | 0.0 | En developpement |
155 | Soudan | 4.545455 | 120.000000 | 1.0 | 0.000000 | -1.98 | -19.785436 | 3022.660865 | 4614.0 | 40.0 | 0.0 | 4457.0 | 0.0 | Pays moins avancé (PMA) |
df_original.columns
Index(['Zone', 'Ratio volaille/carne en %', 'Variation cumulée - Proportion de volaille vs total viande', 'Disponibilité volaille (kg/personne/an)', 'exportation / production en %', 'Stabilite politique', 'Variation cumulée - PIB', 'Variation cumulée - Taux de change en %', 'PIB', 'Tarif EAV en %', 'MNT', 'Distance', 'Cas maladie recense', 'Statut'], dtype='object')
df_original = df_original[['Zone', 'Stabilite politique', 'Ratio volaille/carne en %',
'Variation cumulée - Proportion de volaille vs total viande',
'Disponibilité volaille (kg/personne/an)',
'Variation cumulée - PIB', 'PIB',
'Variation cumulée - Taux de change en %', 'Statut']]
#Non présent : 'exportation / production en %' , 'Tarif EAV en %', 'MNT', 'Distance', 'Cas maladie recense'
"""rank_descendant = ['exportation / production en %', 'Variation cumulée - PIB', 'Variation cumulée - Taux de change en %',
'Tarif EAV en %', 'MNT', 'Distance', 'Cas maladie recense']
rank_ascendant = ['Ratio volaille/carne en %', 'Variation cumulée - Proportion de volaille vs total viande',
'Disponibilité volaille (kg/personne/an)', 'Stabilite politique',
'PIB']
col_str = ['Zone', 'Statut']
for col in df_original:
if col in col_str:
next
elif col in rank_ascendant:
df_original[col].rank()
df_original["rank "+col] = df_original[col].rank(ascending=True)
df_original.drop(columns=col,inplace=True)
else :
df_original[col].rank()
df_original["rank "+col] = df_original[col].rank(ascending=False)
df_original.drop(columns=col,inplace=True)"""
'rank_descendant = [\'exportation / production en %\', \'Variation cumulée - PIB\', \'Variation cumulée - Taux de change en %\',\n \'Tarif EAV en %\', \'MNT\', \'Distance\', \'Cas maladie recense\']\nrank_ascendant = [\'Ratio volaille/carne en %\', \'Variation cumulée - Proportion de volaille vs total viande\',\n \'Disponibilité volaille (kg/personne/an)\', \'Stabilite politique\',\n \'PIB\']\ncol_str = [\'Zone\', \'Statut\']\n\n\nfor col in df_original:\n if col in col_str:\n next\n elif col in rank_ascendant:\n df_original[col].rank()\n df_original["rank "+col] = df_original[col].rank(ascending=True)\n df_original.drop(columns=col,inplace=True)\n else : \n df_original[col].rank()\n df_original["rank "+col] = df_original[col].rank(ascending=False)\n df_original.drop(columns=col,inplace=True)'
df_original
Zone | Stabilite politique | Ratio volaille/carne en % | Variation cumulée - Proportion de volaille vs total viande | Disponibilité volaille (kg/personne/an) | Variation cumulée - PIB | PIB | Variation cumulée - Taux de change en % | Statut | |
---|---|---|---|---|---|---|---|---|---|
0 | Afghanistan | -2.80 | 22.222222 | 0.000000 | 2.0 | -27.660894 | 2096.1 | 21.313925 | Pays moins avancé (PMA) |
1 | Afrique du Sud | -0.28 | 58.730159 | 5.519604 | 37.0 | -4.577614 | 13950.5 | 10.836361 | Pays moins avancé (PMA) |
2 | Albanie | 0.38 | 27.906977 | 51.602564 | 12.0 | 13.666119 | 12771.0 | -13.081201 | En developpement |
3 | Algérie | -0.92 | 35.000000 | -4.761905 | 7.0 | -6.517634 | 11809.5 | 21.708918 | En developpement |
5 | Angola | -0.38 | 44.000000 | -9.090909 | 11.0 | -18.119206 | 7216.1 | 280.579416 | Pays moins avancé (PMA) |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
171 | Uruguay | 1.05 | 15.000000 | 143.386243 | 9.0 | -1.325572 | 23107.0 | 51.882994 | En developpement |
172 | Vanuatu | 0.70 | 40.000000 | 22.093023 | 16.0 | -8.188176 | 3031.2 | 1.513313 | En developpement |
173 | Viet Nam | 0.23 | 23.809524 | 61.538462 | 10.0 | 17.429591 | 9050.7 | 3.530142 | En developpement |
174 | Zambie | 0.15 | 15.000000 | 11.111111 | 3.0 | -4.673833 | 3395.5 | 110.289234 | Pays moins avancé (PMA) |
175 | Zimbabwe | -0.71 | 9.615385 | 30.000000 | 5.0 | -9.293250 | 2331.8 | 0.000000 | Pays moins avancé (PMA) |
154 rows × 9 columns
df_original.describe()
Stabilite politique | Ratio volaille/carne en % | Variation cumulée - Proportion de volaille vs total viande | Disponibilité volaille (kg/personne/an) | Variation cumulée - PIB | PIB | Variation cumulée - Taux de change en % | |
---|---|---|---|---|---|---|---|
count | 154.000000 | 154.000000 | 154.000000 | 154.000000 | 154.000000 | 154.000000 | 154.000000 |
mean | -0.150130 | 41.634219 | 14.739036 | 21.084416 | 1.970229 | 17092.278571 | 18.674009 |
std | 0.906732 | 21.545317 | 35.430104 | 17.844261 | 12.850815 | 18510.330410 | 58.481823 |
min | -2.800000 | 0.000000 | -100.000000 | 0.000000 | -47.310088 | 750.800000 | -13.081201 |
25% | -0.670000 | 23.599440 | -1.050166 | 6.000000 | -4.653154 | 3998.000000 | -3.104735 |
50% | -0.055000 | 41.666667 | 5.902845 | 18.000000 | 1.432695 | 11713.000000 | 0.859902 |
75% | 0.415000 | 59.743590 | 18.825356 | 33.000000 | 7.839840 | 23474.575000 | 17.021548 |
max | 1.600000 | 90.000000 | 229.411765 | 80.000000 | 79.809080 | 122978.000000 | 473.521841 |
df_original.info()
<class 'pandas.core.frame.DataFrame'> Index: 154 entries, 0 to 175 Data columns (total 9 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Zone 154 non-null object 1 Stabilite politique 154 non-null float64 2 Ratio volaille/carne en % 154 non-null float64 3 Variation cumulée - Proportion de volaille vs total viande 154 non-null float64 4 Disponibilité volaille (kg/personne/an) 154 non-null float64 5 Variation cumulée - PIB 154 non-null float64 6 PIB 154 non-null float64 7 Variation cumulée - Taux de change en % 154 non-null float64 8 Statut 154 non-null object dtypes: float64(7), object(2) memory usage: 12.0+ KB
#Sélection des variables numériques
df_valeurs = df_original.select_dtypes(include='number')
for col in df_valeurs:
sns.boxplot(data=df_original, y=col, palette="Set2")
plt.title(col)
show_outliers_str(df_original, col)
plt.show()
Remarques :
sns.pairplot(df_original, hue="Statut")
<seaborn.axisgrid.PairGrid at 0x17924b81b50>
Remarques :
Matrice de corrélation
Selon la méthode de Spearman due aux nombreuses variables qui ne suivent pas de loi normale
#Création de la matrice
matrice_corr = df_valeurs.corr(method="spearman")
#Affichage de la heatmap
sns.heatmap(matrice_corr, annot=True, cmap="YlGnBu")
<Axes: >
#Récupération des statuts pour différentes aides à la visualisations
statuts = df_original["Statut"]
statuts.shape
(154,)
#Valeurs
X = df_valeurs.values
X.shape
(154, 7)
columns_names = df_valeurs.columns
columns_names.shape
(7,)
zones = df_original["Zone"]
zones.shape
(154,)
#Définition de la technique utilisée
scaler = StandardScaler()
#Ajustement et application aux données
X_scaled = scaler.fit_transform(X)
#Vérification du travail - Attendu : mean == 0 & std == 1
pd.DataFrame(X_scaled).describe().round(2).iloc[1:3,:]
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
mean | 0.0 | 0.0 | -0.0 | 0.0 | 0.0 | -0.0 | -0.0 |
std | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 |
Par le calcul des valeurs en fonction des coefficients attribués au composantes
#Définition de la l'objet utilisé
pca = PCA()
#Ajustement et application aux données déjà standardisées
X_pca = pca.fit_transform(X_scaled)
pd.DataFrame(X_pca)
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
0 | -1.880259 | 2.062289 | -1.330000 | -2.405415 | -0.499373 | 1.023903 | -0.334697 |
1 | 0.941734 | 0.618582 | 0.173688 | -0.381914 | 0.544270 | 0.154930 | -0.256669 |
2 | -0.952632 | -1.359731 | 0.311112 | 0.452148 | 0.417802 | -0.233761 | 0.041447 |
3 | -0.742771 | 0.762991 | -0.263905 | -0.836004 | -0.584996 | 0.056411 | 0.170349 |
4 | -0.142043 | 3.222142 | -2.876614 | 1.527697 | -0.709295 | -1.475165 | 0.311198 |
... | ... | ... | ... | ... | ... | ... | ... |
149 | -1.334152 | -2.391790 | -2.359739 | 1.094720 | 1.752884 | -0.300198 | 0.316941 |
150 | -0.040006 | -0.328033 | -0.295920 | -0.687386 | 0.534045 | -1.164239 | 0.046609 |
151 | -1.404294 | -1.303168 | 0.257723 | 0.818632 | 0.520736 | -0.209544 | -0.050239 |
152 | -1.215138 | 0.523591 | -1.319086 | 0.407111 | -0.680352 | -1.352806 | -0.183636 |
153 | -1.701333 | -0.161361 | -0.801318 | -1.112686 | -0.133228 | -0.217026 | -0.511426 |
154 rows × 7 columns
#Récupération des variances expliquées
variances_explained = (pca.explained_variance_ratio_*100).round(2)
variances_explained
array([33.02, 19.71, 15.95, 10.74, 10.33, 6.85, 3.39])
#Variances cumulées
var_exp_cum = variances_explained.cumsum().round(1)
var_exp_cum
array([ 33. , 52.7, 68.7, 79.4, 89.8, 96.6, 100. ])
#Création de la liste des components pour notre graphique
x_list = range (1, len(var_exp_cum)+1)
list(x_list)
[1, 2, 3, 4, 5, 6, 7]
#Visualisation du scree plot
plt.bar(x_list, variances_explained)
#plt.plot(x_list, var_exp_cum, c="red", marker='o')
plt.xlabel("Dimension")
plt.ylabel("Variance expliquée")
plt.title("Variance expliquée par dimension")
plt.show(block=False)
# Calcul du cosinus carré des variables
cos_squared = np.square(pca.components_)
# Création d'un dataframe avec le cosinus carré des variables
df_cos_squared = pd.DataFrame(cos_squared, columns=['F{}'.format(i+1) for i in range(X.shape[1])])
df_cos_squared.index = columns_names
#Vérification total des cos2 à 1
df_cos_squared["Total cos2"] = df_cos_squared.sum(axis=1)
df_cos_squared
F1 | F2 | F3 | F4 | F5 | F6 | F7 | Total cos2 | |
---|---|---|---|---|---|---|---|---|
Stabilite politique | 0.149707 | 0.201190 | 0.087617 | 0.339007 | 0.047047 | 0.175124 | 0.000308 | 1.0 |
Ratio volaille/carne en % | 0.266741 | 0.145017 | 0.153559 | 0.002388 | 0.040628 | 0.128724 | 0.262943 | 1.0 |
Variation cumulée - Proportion de volaille vs total viande | 0.001975 | 0.092984 | 0.134769 | 0.002258 | 0.422871 | 0.087472 | 0.257670 | 1.0 |
Disponibilité volaille (kg/personne/an) | 0.025998 | 0.001425 | 0.045754 | 0.019916 | 0.460570 | 0.020886 | 0.425452 | 1.0 |
Variation cumulée - PIB | 0.001699 | 0.197579 | 0.513225 | 0.069987 | 0.012188 | 0.191827 | 0.013496 | 1.0 |
PIB | 0.542287 | 0.004994 | 0.057952 | 0.043583 | 0.016425 | 0.294831 | 0.039927 | 1.0 |
Variation cumulée - Taux de change en % | 0.011593 | 0.356811 | 0.007124 | 0.522862 | 0.000272 | 0.101135 | 0.000204 | 1.0 |
#Affichage visuel
i=131
for component in df_cos_squared[["F1", "F2", "F3"]]:
df_temp = df_cos_squared[component]
plt.subplot(i)
plt.subplots_adjust(left=0.2, right=2, wspace=0.2)
sns.lineplot(df_temp)
plt.ylabel("cos2 de variable")
plt.xticks(rotation=90)
plt.ylim(0, 0.55)
plt.grid(which="both")
plt.title(component)
i += 1
plt.show()
Remarques :
#F1 et F2
X_proj = pca.transform(X_scaled)
x_y = (0,1)
correlation_graph(pca, x_y, columns_names)
plt.show()
display_factorial_planes(X_proj, x_y, clusters=statuts) #, labels=zones.tolist()
#F2 et F3
x_y = (1,2)
correlation_graph(pca, x_y, columns_names)
#Définition des 3 axes pour la représentation 3D
x = X_proj[:,0] #F1
y = X_proj[:,1] #F2
z = X_proj[:,2] #F3
#Spatialisation 3D avec F3 ajouté
fig = go.Figure(data=[go.Scatter3d(x=x, y=y, z=z,
mode='markers',
hovertext=zones.tolist(),
marker=dict(
size=10, color=z, colorscale='plotly3',
opacity=0.8, reversescale=True))])
fig.update_layout(margin=dict(l=0, r=0, b=0, t=0),
scene=dict(
xaxis=dict(range=[-4, 4]),
yaxis=dict(range=[-4, 4]),
zaxis=dict(range=[-4, 4])))
fig.show()
#Zoom sur la zone des pays jugé interessants (quart en bas-droite)
df_projete_F1_F2 = pd.DataFrame(X_proj)
df_projete_F1_F2.index = zones
df_temp = df_projete_F1_F2.loc[(df_projete_F1_F2[0] > 0) & (df_projete_F1_F2[1] < 0)]
#Affichage des pays interessant sur F1 & F2
sns.scatterplot(df_temp, x=0, y=1)
for zone in df_temp.index:
X = df_temp.loc[df_temp.index==zone,[0]].values[0]
Y = df_temp.loc[df_temp.index==zone,[1]].values[0]
plt.text(x=X, y=Y, s=zone)
list_pays_interessant_ACP = df_temp.index.tolist()
print("Nombre de pays interessant :",len(list_pays_interessant_ACP))
list_pays_interessant_ACP
Nombre de pays interessant : 35
['Australie', 'Bahamas', 'Bélarus', 'Bulgarie', 'Canada', 'Chili', 'Chine - RAS de Macao', 'Chypre', 'Costa Rica', 'Dominique', 'Espagne', "États-Unis d'Amérique", 'Finlande', 'Grenade', 'Guyana', 'Islande', 'Italie', 'Japon', 'Kiribati', 'Maldives', 'Malte', 'Nauru', 'Norvège', 'Nouvelle-Zélande', 'Panama', 'Portugal', 'Qatar', 'République de Corée', 'Roumanie', "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord", 'Saint-Kitts-et-Nevis', 'Seychelles', 'Suède', 'Suisse', 'Tchéquie']
#Récupération des statuts pour différentes aides à la visualisations
statuts = df_original["Statut"]
statuts.shape
(154,)
#Récupération uniquement des valeurs numériques
df_valeurs = df_original.select_dtypes("number")
#Valeurs
X = df_valeurs.values
X.shape
(154, 7)
#En-têtes colonnes
columns_names = df_valeurs.columns
columns_names.shape
(7,)
#Pays
zones = df_original["Zone"]
zones.shape
(154,)
#Définition de la technique utilisée
scaler = preprocessing.StandardScaler()
#Ajustement et application aux données
X_scaled = scaler.fit_transform(X)
#Vérification du travail - Attendu : mean == 0 & std == 1
pd.DataFrame(X_scaled).describe().round(2).iloc[1:3,:]
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
---|---|---|---|---|---|---|---|
mean | 0.0 | 0.0 | -0.0 | 0.0 | 0.0 | -0.0 | -0.0 |
std | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 |
Z = linkage(X_scaled, method="ward")
Z[:5]
array([[ 31. , 33. , 0.18191767, 2. ], [ 64. , 91. , 0.38249551, 2. ], [ 1. , 53. , 0.38756286, 2. ], [ 42. , 58. , 0.41442566, 2. ], [111. , 153. , 0.41458065, 2. ]])
fig, ax = plt.subplots(1, 1, figsize=(40,15))
_ = dendrogram(Z, ax=ax, labels=zones.tolist())
plt.title("Hierarchical Clustering Dendrogram")
ax.set_xlabel("Zone")
ax.set_ylabel("Distance")
ax.tick_params(axis='x', which='major', labelsize=15)
ax.tick_params(axis='y', which='major', labelsize=15)
#Définition du nombre de cluster voulu (coupe dans l'arbre CAH)
k=3
model = AgglomerativeClustering(n_clusters=k, linkage="ward")
model.fit(X_scaled)
AgglomerativeClustering(n_clusters=3)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
AgglomerativeClustering(n_clusters=3)
model.labels_
array([0, 0, 0, 0, 2, 1, 1, 2, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 2, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0], dtype=int64)
df_temp = pd.DataFrame(X_scaled)
df_temp.columns = columns_names
df_temp["Cluster"] = model.labels_
df_dendo = df_temp.groupby("Cluster").mean().reset_index()
my_palette = plt.cm.get_cmap("Set2", len(df_dendo.index))
for row in range(0, len(df_dendo.index)):
make_spider(df_dendo, row=row, title='Cluster '+str(row+1), color=my_palette(row))
#Récupération des pays intéressant
df_temp.index = df_original["Zone"]
list_pays_interessant_dendro = df_temp.loc[df_temp["Cluster"] == 1].index.tolist()
print("Il y a {} pays concernés".format(len(list_pays_interessant_dendro)))
list_pays_interessant_dendro
Il y a 43 pays concernés
['Antigua-et-Barbuda', 'Arabie saoudite', 'Australie', 'Bahamas', 'Bahreïn', 'Barbade', 'Canada', 'Chili', 'Chine - RAS de Macao', 'Chypre', 'Dominique', 'Espagne', "États-Unis d'Amérique", 'Fidji', 'Finlande', 'Grenade', 'Islande', 'Israël', 'Italie', 'Jamaïque', 'Japon', 'Koweït', 'Malaisie', 'Malte', 'Maurice', 'Micronésie (États fédérés de)', 'Nauru', 'Norvège', 'Nouvelle-Zélande', 'Panama', 'Portugal', 'Qatar', 'République de Corée', "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord", 'Sainte-Lucie', 'Saint-Kitts-et-Nevis', 'Saint-Vincent-et-les Grenadines', 'Samoa', 'Seychelles', 'Suède', 'Suisse', 'Tchéquie', 'Trinité-et-Tobago']
sns.pairplot(df_temp, hue="Cluster")
<seaborn.axisgrid.PairGrid at 0x1792bf49b50>
#Sélection des caractéristiques pertinentes
features = df_valeurs
#Normalisation des données
scaler = StandardScaler()
scaled_features = scaler.fit_transform(features)
Calcul du coût (détermine le nombre de clusters le plus efficient)
#Liste des coûts pour x clusters
list_inertia = []
#Nombre de cluster à tester
k_range = range(1,20)
for k in k_range:
model = KMeans(n_clusters=k).fit(scaled_features)
list_inertia.append(model.inertia_)
#Affichage des coûts - Méthode du coude
sns.lineplot(x=k_range, y=list_inertia)
plt.xlabel("Nombre de cluster")
plt.ylabel("Coût du modèle (inertia)")
Text(0, 0.5, 'Coût du modèle (inertia)')
list_ecarts = []
mean = np.mean(list_inertia)
i=0
for k in list_inertia:
ecart = abs(k - mean)
i += 1
list_ecarts.append(ecart)
ecart_min = min(list_ecarts)
n_cluster = list_ecarts.index(ecart_min)+1
n_cluster
7
# Appliquer l'algorithme de clustering (k-means)
model = KMeans(n_clusters=n_cluster)
df_original['Cluster'] = model.fit_predict(scaled_features)
#Centroïdes
centroides = model.cluster_centers_
#Inertia - Distance cumulée entre un centroïde et ses points
inertia = model.inertia_
inertia
403.78981739169905
sns.pairplot(data=df_original, hue="Cluster");
plt.show()
df_projete_F1_F2 = df_projete_F1_F2[[0,1]]
df_projete_F1_F2.head()
0 | 1 | |
---|---|---|
Zone | ||
Afghanistan | -1.880259 | 2.062289 |
Afrique du Sud | 0.941734 | 0.618582 |
Albanie | -0.952632 | -1.359731 |
Algérie | -0.742771 | 0.762991 |
Angola | -0.142043 | 3.222142 |
#Sélection des 2 premières composantes principales
features = df_projete_F1_F2
#Normalisation des données
scaler = StandardScaler()
scaled_features = scaler.fit_transform(features)
Calcul du coût (détermine le nombre de clusters le plus efficient)
#Liste des coûts pour x clusters
list_inertia = []
#Nombre de cluster à tester
k_range = range(1,20)
for k in k_range:
model = KMeans(n_clusters=k).fit(scaled_features)
list_inertia.append(model.inertia_)
from sklearn.metrics import silhouette_score
silhouettes = []
K = range(2, 10)
for k in K:
kmeanModel = KMeans(n_clusters=k)
kmeanModel.fit(scaled_features)
silhouettes.append(silhouette_score(scaled_features, kmeanModel.labels_))
#Affichage des coûts - Méthode du coude
sns.lineplot(x=k_range, y=list_inertia)
plt.xlabel("Nombre de cluster")
plt.ylabel("Coût du modèle (inertia)")
Text(0, 0.5, 'Coût du modèle (inertia)')
plt.figure(figsize=(10,4))
plt.plot(K, silhouettes, 'bx-')
plt.xlabel('k')
plt.ylabel('Score de silhouette')
plt.title('Le score de silhouette montrant le k optimal')
plt.show()
"""
#Sélection auto du nombre de clusters selon le coude
list_ecarts = []
mean = np.mean(list_inertia)
i=0
for k in list_inertia:
ecart = abs(k - mean)
i += 1
list_ecarts.append(ecart)
ecart_min = min(list_ecarts)
n_cluster = list_ecarts.index(ecart_min)+1
"""
'\n#Sélection auto du nombre de clusters selon le coude\nlist_ecarts = []\nmean = np.mean(list_inertia)\ni=0\n\nfor k in list_inertia:\n ecart = abs(k - mean)\n i += 1\n list_ecarts.append(ecart)\n\necart_min = min(list_ecarts)\nn_cluster = list_ecarts.index(ecart_min)+1\n'
#Choix du nombre de clusters
#n_clusters = n_cluster
n_clusters = 4
# Appliquer l'algorithme de clustering (k-means)
model = KMeans(n_clusters=n_clusters)
model.fit(scaled_features)
df_original['Cluster'] = model.fit_predict(scaled_features)
#Récupération des centroïdes
centroides = model.cluster_centers_
centroides
array([[-1.11271601, -0.66735214], [ 1.17867231, -0.53882106], [-0.33337686, 2.35529953], [-0.07997519, 0.39710942]])
#Visualisation des individus, clusters et centroïdes sur PC1 et PC2
sns.scatterplot(data=centroides, x=centroides[:,0], y=centroides[:,1], c="red", marker="x")
sns.scatterplot(data=df_projete_F1_F2, x=0, y=1, hue=model.fit_predict(scaled_features))
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.show()
sns.pairplot(data=df_original, hue="Cluster");
Récupération du cluster correspondant à la plus haute Stabilité politique car il correpond au cluster où la plus part des variables sont hautes
#Récupération du cluster correspondant à la plus haute Stabilité politique
dict_PIB_max = {}
for cluster in df_original["Cluster"].unique().tolist():
PIB_max = df_original.loc[df_original["Cluster"] == cluster, "PIB"].max()
dict_PIB_max[cluster] = PIB_max
cluster_interessant = max(dict_PIB_max, key=dict_PIB_max.get)
dict_PIB_max
{2: 27582.8, 3: 26943.3, 0: 28604.9, 1: 122978.0}
cluster_interessant
1
list_pays_interessant_kmeans_PCA = df_original.loc[df_original["Cluster"] == cluster_interessant, "Zone"].tolist()
#Rappel des listes
"""
list_pays_interessant_ACP
list_pays_interessant_dendro
list_pays_interessant_kmeans_PCA
"""
'\nlist_pays_interessant_ACP\nlist_pays_interessant_dendro\nlist_pays_interessant_kmeans_PCA\n'
common = list(set(list_pays_interessant_ACP) & set(list_pays_interessant_dendro) & set(list_pays_interessant_kmeans_PCA))
print("Il y a {} pays en communs qui sont les suivants :".format(len(common)))
common
Il y a 28 pays en communs qui sont les suivants :
['Islande', 'Dominique', 'Norvège', 'Suède', 'Finlande', 'Grenade', 'République de Corée', 'Suisse', 'Nauru', 'Canada', 'Portugal', 'Chine - RAS de Macao', 'Nouvelle-Zélande', 'Malte', "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord", 'Japon', 'Tchéquie', "États-Unis d'Amérique", 'Chypre', 'Chili', 'Australie', 'Panama', 'Saint-Kitts-et-Nevis', 'Italie', 'Qatar', 'Bahamas', 'Espagne', 'Seychelles']
Idée :
Faire une heatmap avec un tableau de contingence : en ordonnée tous les pays et en abscisse toutes les listes
df_heatmap = df_original[["Zone"]]
df_heatmap["ACP"] = 0
df_heatmap["Dendrogram"] = 0
df_heatmap["Kmeans_pca"] = 0
for pays in df_heatmap["Zone"]:
if pays in list_pays_interessant_ACP :
df_heatmap.loc[df_heatmap["Zone"] == pays, "ACP"] = 1
if pays in list_pays_interessant_dendro :
df_heatmap.loc[df_heatmap["Zone"] == pays, "Dendrogram"] = 1
if pays in list_pays_interessant_kmeans_PCA :
df_heatmap.loc[df_heatmap["Zone"] == pays, "Kmeans_pca"] = 1
df_heatmap.set_index("Zone", inplace=True)
df_heatmap["Total"] = df_heatmap["ACP"] + df_heatmap["Dendrogram"] + df_heatmap["Kmeans_pca"]
pays_todrop = df_heatmap.loc[df_heatmap["Total"] == 0].index.tolist()
df_heatmap.drop(index=pays_todrop, inplace=True)
plt.figure(figsize=(5,10))
sns.heatmap(df_heatmap.sort_values("Total", ascending=False))
print("Nombre totaux de pays concernés : {}".format(len(df_heatmap)))
Nombre totaux de pays concernés : 50
df_acp = df_projete_F1_F2.loc[df_projete_F1_F2.index.isin(list_pays_interessant_ACP)]
df_dendrogram = df_projete_F1_F2.loc[df_projete_F1_F2.index.isin(list_pays_interessant_dendro)]
df_kmeans_pca = df_projete_F1_F2.loc[df_projete_F1_F2.index.isin(list_pays_interessant_kmeans_PCA)]
list_df = [df_dendrogram, df_acp, df_kmeans_pca]
methodes = ["Dendogram", "ACP", "Kmeans sur ACP"]
from scipy.stats import kstest
for i, df in enumerate(list_df):
#Récupération uniquement des valeurs
df_temp_values = df.select_dtypes("number")
print("\n=====================================\n",methodes[i],
"\n=====================================\n",
str(df.index.values),"\n-------")
for col in df_temp_values.columns:
print("-------","PC"+str(col+1),"-------")
#Test de Kolmogorov-Smirnov en comparant à une distribution normale
statistic, p_value = kstest(df_temp_values[col], 'norm')
#Affiche les résultats du test
print("Statistique du test : {}".format(statistic))
print("Valeur P : {}".format(p_value))
#Interprète les résultats
alpha = 0.05 #Niveau de signification
if p_value > alpha:
print("Les données semblent suivre une distribution normale.")
else:
print("Les données ne suivent pas une distribution normale.")
sns.histplot(df_temp_values[col])
plt.show()
===================================== Dendogram ===================================== ['Antigua-et-Barbuda' 'Arabie saoudite' 'Australie' 'Bahamas' 'Bahreïn' 'Barbade' 'Canada' 'Chili' 'Chine - RAS de Macao' 'Chypre' 'Dominique' 'Espagne' "États-Unis d'Amérique" 'Fidji' 'Finlande' 'Grenade' 'Islande' 'Israël' 'Italie' 'Jamaïque' 'Japon' 'Koweït' 'Malaisie' 'Malte' 'Maurice' 'Micronésie (États fédérés de)' 'Nauru' 'Norvège' 'Nouvelle-Zélande' 'Panama' 'Portugal' 'Qatar' 'République de Corée' "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord" 'Sainte-Lucie' 'Saint-Kitts-et-Nevis' 'Saint-Vincent-et-les Grenadines' 'Samoa' 'Seychelles' 'Suède' 'Suisse' 'Tchéquie' 'Trinité-et-Tobago'] ------- ------- PC1 ------- Statistique du test : 0.704285659374785 Valeur P : 5.902137585801043e-22 Les données ne suivent pas une distribution normale.
------- PC2 ------- Statistique du test : 0.2759942510946001 Valeur P : 0.0021854915426771093 Les données ne suivent pas une distribution normale.
===================================== ACP ===================================== ['Australie' 'Bahamas' 'Bélarus' 'Bulgarie' 'Canada' 'Chili' 'Chine - RAS de Macao' 'Chypre' 'Costa Rica' 'Dominique' 'Espagne' "États-Unis d'Amérique" 'Finlande' 'Grenade' 'Guyana' 'Islande' 'Italie' 'Japon' 'Kiribati' 'Maldives' 'Malte' 'Nauru' 'Norvège' 'Nouvelle-Zélande' 'Panama' 'Portugal' 'Qatar' 'République de Corée' 'Roumanie' "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord" 'Saint-Kitts-et-Nevis' 'Seychelles' 'Suède' 'Suisse' 'Tchéquie'] ------- ------- PC1 ------- Statistique du test : 0.5603567726327162 Valeur P : 6.927449904112383e-11 Les données ne suivent pas une distribution normale.
------- PC2 ------- Statistique du test : 0.5002126215973748 Valeur P : 1.267879155799694e-08 Les données ne suivent pas une distribution normale.
===================================== Kmeans sur ACP ===================================== ['Antigua-et-Barbuda' 'Arabie saoudite' 'Australie' 'Bahamas' 'Bahreïn' 'Barbade' 'Canada' 'Chili' 'Chine - RAS de Macao' 'Chypre' 'Costa Rica' 'Dominique' 'Espagne' "États-Unis d'Amérique" 'Fidji' 'Finlande' 'Grenade' 'Islande' 'Israël' 'Italie' 'Jamaïque' 'Japon' 'Koweït' 'Malaisie' 'Malte' 'Maurice' 'Micronésie (États fédérés de)' 'Nauru' 'Norvège' 'Nouvelle-Zélande' 'Panama' 'Portugal' 'Qatar' 'République de Corée' "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord" 'Sainte-Lucie' 'Saint-Kitts-et-Nevis' 'Saint-Vincent-et-les Grenadines' 'Samoa' 'Seychelles' 'Suède' 'Suisse' 'Tchéquie' 'Trinité-et-Tobago'] ------- ------- PC1 ------- Statistique du test : 0.7053427418272163 Valeur P : 1.561336787838266e-22 Les données ne suivent pas une distribution normale.
------- PC2 ------- Statistique du test : 0.2770513335470314 Valeur P : 0.0017736078081265205 Les données ne suivent pas une distribution normale.
#Récupération des pays concernés par cette méthode
df_temp_dendro = df_original.loc[df_original["Zone"].isin(list_pays_interessant_dendro)][['Zone', 'Stabilite politique', 'Ratio volaille/carne en %',
'Variation cumulée - Proportion de volaille vs total viande',
'Disponibilité volaille (kg/personne/an)', 'Variation cumulée - PIB',
'PIB', 'Variation cumulée - Taux de change en %']]
df_temp_dendro["Cluster"] = "0" #pour groupby dessus
df_temp_dendro.set_index("Zone", inplace=True)
df_temp_dendro = df_temp_dendro.groupby("Cluster").mean().reset_index()
df_temp_dendro
Cluster | Stabilite politique | Ratio volaille/carne en % | Variation cumulée - Proportion de volaille vs total viande | Disponibilité volaille (kg/personne/an) | Variation cumulée - PIB | PIB | Variation cumulée - Taux de change en % | |
---|---|---|---|---|---|---|---|---|
0 | 0 | 0.695349 | 50.381174 | 5.66744 | 40.581395 | -3.343409 | 37385.57907 | 0.93754 |
#Récupération des pays concernés par cette méthode
df_temp_acp = df_original.loc[df_original["Zone"].isin(list_pays_interessant_ACP)][['Zone', 'Stabilite politique', 'Ratio volaille/carne en %',
'Variation cumulée - Proportion de volaille vs total viande',
'Disponibilité volaille (kg/personne/an)', 'Variation cumulée - PIB',
'PIB', 'Variation cumulée - Taux de change en %']]
df_temp_acp["Cluster"] = "1" #pour groupby dessus
df_temp_acp.set_index("Zone", inplace=True)
df_temp_acp = df_temp_acp.groupby("Cluster").mean().reset_index()
df_temp_acp
Cluster | Stabilite politique | Ratio volaille/carne en % | Variation cumulée - Proportion de volaille vs total viande | Disponibilité volaille (kg/personne/an) | Variation cumulée - PIB | PIB | Variation cumulée - Taux de change en % | |
---|---|---|---|---|---|---|---|---|
0 | 1 | 0.748571 | 41.96452 | 6.886203 | 31.857143 | 2.123106 | 39173.451429 | 1.649405 |
#Récupération des pays concernés par cette méthode
df_temp_Kmeans_acp = df_original.loc[df_original["Zone"].isin(list_pays_interessant_kmeans_PCA)][['Zone', 'Stabilite politique', 'Ratio volaille/carne en %',
'Variation cumulée - Proportion de volaille vs total viande',
'Disponibilité volaille (kg/personne/an)', 'Variation cumulée - PIB',
'PIB', 'Variation cumulée - Taux de change en %']]
df_temp_Kmeans_acp["Cluster"] = "2" #pour groupby dessus
df_temp_Kmeans_acp.set_index("Zone", inplace=True)
df_temp_Kmeans_acp = df_temp_Kmeans_acp.groupby("Cluster").mean().reset_index()
df_temp_Kmeans_acp
Cluster | Stabilite politique | Ratio volaille/carne en % | Variation cumulée - Proportion de volaille vs total viande | Disponibilité volaille (kg/personne/an) | Variation cumulée - PIB | PIB | Variation cumulée - Taux de change en % | |
---|---|---|---|---|---|---|---|---|
0 | 2 | 0.693409 | 50.417965 | 5.59221 | 40.25 | -3.15123 | 36994.275 | 1.129569 |
#Concaténation des 3 dataframe temporaire
df_methode_temp = pd.concat([df_temp_Kmeans_acp, df_temp_acp, df_temp_dendro])
methodes = ["Dendrogram", "ACP", "Kmeans sur PC1 & PC2"]
df_methode_temp.reset_index(inplace=True)
df_methode_temp.drop(columns={"index"}, inplace=True)
df_methode_temp
Cluster | Stabilite politique | Ratio volaille/carne en % | Variation cumulée - Proportion de volaille vs total viande | Disponibilité volaille (kg/personne/an) | Variation cumulée - PIB | PIB | Variation cumulée - Taux de change en % | |
---|---|---|---|---|---|---|---|---|
0 | 2 | 0.693409 | 50.417965 | 5.592210 | 40.250000 | -3.151230 | 36994.275000 | 1.129569 |
1 | 1 | 0.748571 | 41.964520 | 6.886203 | 31.857143 | 2.123106 | 39173.451429 | 1.649405 |
2 | 0 | 0.695349 | 50.381174 | 5.667440 | 40.581395 | -3.343409 | 37385.579070 | 0.937540 |
#Récupération des données seulement
values_spider = df_methode_temp.values
#Définition de la technique utilisée
scaler = StandardScaler()
#Ajustement et application aux données
X_scaled = scaler.fit_transform(values_spider)
df_spider_methode = pd.DataFrame(X_scaled)
df_spider_methode.columns = df_methode_temp.columns
#Vérification du travail - Attendu : mean == 0 & std == 1
df_spider_methode.describe().round(0).iloc[1:3,:]
Cluster | Stabilite politique | Ratio volaille/carne en % | Variation cumulée - Proportion de volaille vs total viande | Disponibilité volaille (kg/personne/an) | Variation cumulée - PIB | PIB | Variation cumulée - Taux de change en % | |
---|---|---|---|---|---|---|---|---|
mean | 0.0 | 0.0 | -0.0 | 0.0 | -0.0 | -0.0 | -0.0 | -0.0 |
std | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 |
df_spider_methode
Cluster | Stabilite politique | Ratio volaille/carne en % | Variation cumulée - Proportion de volaille vs total viande | Disponibilité volaille (kg/personne/an) | Variation cumulée - PIB | PIB | Variation cumulée - Taux de change en % | |
---|---|---|---|---|---|---|---|---|
0 | 1.224745 | -0.744714 | 0.711728 | -0.769583 | 0.665663 | -0.668830 | -0.903263 | -0.363364 |
1 | 0.000000 | 1.413535 | -1.414203 | 1.412316 | -1.413419 | 1.413535 | 1.394015 | 1.365310 |
2 | -1.224745 | -0.668821 | 0.702475 | -0.642732 | 0.747756 | -0.744705 | -0.490752 | -1.001946 |
my_palette = plt.cm.get_cmap("Set2", len(df_spider_methode.index))
for row in range(0, len(df_spider_methode.index)):
make_spider(df_spider_methode, row=row, title='Methode '+ methodes[row], color=my_palette(row))
Remarques sur les le choix des pays selon la méthode :
#Récupération des variables PC1 & PC2 pour les pays sélectionnés
df_kmeans_pca = df_projete_F1_F2.loc[df_projete_F1_F2.index.isin(list_pays_interessant_kmeans_PCA)]
df_kmeans_pca.shape
(44, 2)
#Récupération des variables originales pour les pays sélectionnés
df_temp = df_original.loc[df_original["Zone"].isin(list_pays_interessant_kmeans_PCA)]
df_temp = df_temp.set_index("Zone")
df_kmeans_pca = df_kmeans_pca.merge(df_original, on="Zone")
df_kmeans_pca.shape
(44, 12)
#Récupération des pays concernés
list_zones = df_kmeans_pca.Zone.to_list()
#Sélection des caractéristiques pertinentes
features = df_original.loc[df_original["Zone"].isin(list_zones)]
features = features[["Zone",'Stabilite politique', 'Ratio volaille/carne en %',
'Variation cumulée - Proportion de volaille vs total viande',
'Disponibilité volaille (kg/personne/an)',
'PIB','Variation cumulée - Taux de change en %']] #, 'Variation cumulée - PIB'
features.set_index("Zone", inplace=True)
columns_names = features.columns
#Normalisation des données
scaler = StandardScaler()
scaled_features = scaler.fit_transform(features)
#Appel du model
model = PCA()
#Fit du model sur les valeurs
model.fit(scaled_features)
#Création de la matrice des composantes principales
X_pca = model.transform(scaled_features)
#Variance expliquée
model.explained_variance_ratio_ * 100
array([41.32961659, 19.44882793, 15.26607706, 11.35935361, 9.59863363, 2.99749118])
#F1 et F2
x_y = (0,1)
correlation_graph(model, x_y, columns_names)
plt.show()
display_factorial_planes(X_pca, x_y, labels=features.index)
X_pca.shape
(44, 6)
#Récupération de PC1 et PC2 -> 60% de variance expliquée -> assez représentatifs des variables
scaled_features = X_pca[:,[0,1]]
scaled_features.shape
(44, 2)
Calcul du coût (détermine le nombre de clusters le plus efficient)
#Liste des coûts pour x clusters
list_inertia = []
#Nombre de cluster à tester
k_range = range(1,20)
for k in k_range:
model = KMeans(n_clusters=k).fit(scaled_features)
list_inertia.append(model.inertia_)
#Affichage des coûts - Méthode du coude
sns.lineplot(x=k_range, y=list_inertia)
plt.xlabel("Nombre de cluster")
plt.ylabel("Coût du modèle (inertia)")
Text(0, 0.5, 'Coût du modèle (inertia)')
silhouettes = []
K = range(2, 10)
for k in K:
kmeanModel = KMeans(n_clusters=k)
kmeanModel.fit(scaled_features)
silhouettes.append(silhouette_score(scaled_features, kmeanModel.labels_))
plt.figure(figsize=(10,4))
plt.plot(K, silhouettes, 'bx-')
plt.xlabel('k')
plt.ylabel('Score de silhouette')
plt.title('Le score de silhouette montrant le k optimal')
plt.show()
n_cluster = 3
# Appliquer l'algorithme de clustering (k-means)
model = KMeans(n_clusters=n_cluster)
model.fit(scaled_features)
#df_kmeans_pca['Cluster'] = model.fit_predict(scaled_features)
#Centroïdes
centroides = model.cluster_centers_
#Inertia - Distance cumulée entre un centroïde et ses points
inertia = model.inertia_
inertia
52.09410753006094
#Passage en dataframe pour faciliter l'utilisation et la visualisation
df_pca = pd.DataFrame(X_pca)
df_pca.index = features.index
features["Cluster"] = model.fit_predict(scaled_features)
plt.figure(figsize=(12,10))
sns.scatterplot(df_pca, x=0, y=1, hue=features["Cluster"])
for ind, pays in enumerate(df_pca.index):
x = df_pca.iloc[ind, 0] + 0.01
y = df_pca.iloc[ind, 1] + 0.03
plt.text(x=x, y=y, s=pays)
plt.xlabel("Préférence pour la volaille")
plt.ylabel("Stabilité et richesse")
plt.ylim(top=2.5)
plt.legend(bbox_to_anchor=(1.1, 1))
plt.show()
#Nombre de colonnes dans le dataframe
nombre_de_colonnes = len(features.columns)
# Calcule le nombre de lignes nécessaire en fonction du nombre total de colonnes
nombre_de_lignes = -(-nombre_de_colonnes // 2) #Plafond de la division par 2
#Crée une figure et ses sous-graphiques
fig, axs = plt.subplots(nombre_de_lignes, 2, figsize=(15, 5 * nombre_de_lignes))
#Ajuste l'espacement entre les sous-graphiques
plt.tight_layout(h_pad=5)
#Boucle pour créer des boxplots pour chaque colonne
for i, (col, ax) in enumerate(zip(features.columns, axs.flatten())):
#Trace le boxplot dans le subplot actuel
features.boxplot(column=[col], by='Cluster', grid=False, vert=True, ax=ax)
ax.set_title(col)
plt.show()
features.index = list_zones
cluster_0 = features.loc[features["Cluster"] == 0].index.tolist()
cluster_1 = features.loc[features["Cluster"] == 1].index.tolist()
cluster_2 = features.loc[features["Cluster"] == 2].index.tolist()
cluster_0
['Canada', 'Chine - RAS de Macao', 'Chypre', 'Espagne', 'Finlande', 'Italie', 'Japon', 'Malte', 'Norvège', 'Nouvelle-Zélande', 'Panama', 'Portugal', 'République de Corée', "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord", 'Suède', 'Suisse', 'Tchéquie']
cluster_1
['Antigua-et-Barbuda', 'Arabie saoudite', 'Bahreïn', "États-Unis d'Amérique", 'Israël', 'Koweït', 'Malaisie', 'Qatar', 'Saint-Vincent-et-les Grenadines', 'Trinité-et-Tobago']
cluster_2
['Australie', 'Bahamas', 'Barbade', 'Chili', 'Costa Rica', 'Dominique', 'Fidji', 'Grenade', 'Islande', 'Jamaïque', 'Maurice', 'Micronésie (États fédérés de)', 'Nauru', 'Sainte-Lucie', 'Saint-Kitts-et-Nevis', 'Samoa', 'Seychelles']