P9 Produisez une etude de marché avec Python¶

                 * La poule qui chante * 

Sommaire

I - Optimisation des données pré-traitement¶

I.a Exploration du fichier population

I.b Exploration du fichier dispo_alim

I.c Optimisation : Jonction des dataFrames

I.d Optimisation : nettoyage

I.e Optimisation des données : reconstition des data liées

II - Repérage des tendances dominantes¶

II.a Reperage par critères unilateral

II.b Repérage par Projection 2D

III PCA : Principal component analysis

III.a PCA : Initialisation des paramètres

III.b PCA : Inertie & correlation

III.c PCA: Visualisation dans Hyperplan

III.d PCA : Projection des points dans l'espace factoriel

In [3]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
pd.__version__
Out[3]:
'1.5.3'

I- Optimisation des données pré-traitement¶

In [4]:
population = pd.read_csv('Population_2000_2018.csv')
population.head(3)
Out[4]:
Code Domaine Domaine Code zone Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur Symbole Description du Symbole Note
0 OA Séries temporelles annuelles 2 Afghanistan 511 Population totale 3010 Population-Estimations 2000 2000 1000 personnes 20779.953 X Sources internationales sûres NaN
1 OA Séries temporelles annuelles 2 Afghanistan 511 Population totale 3010 Population-Estimations 2001 2001 1000 personnes 21606.988 X Sources internationales sûres NaN
2 OA Séries temporelles annuelles 2 Afghanistan 511 Population totale 3010 Population-Estimations 2002 2002 1000 personnes 22600.770 X Sources internationales sûres NaN
In [5]:
dispo_alim = pd.read_csv('DisponibiliteAlimentaire_2017.csv')
dispo_alim.head(3)
Out[5]:
Code Domaine Domaine Code zone Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur Symbole Description du Symbole
0 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5511 Production 2511 Blé et produits 2017 2017 Milliers de tonnes 4281.0 S Données standardisées
1 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5611 Importations - Quantité 2511 Blé et produits 2017 2017 Milliers de tonnes 2302.0 S Données standardisées
2 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5072 Variation de stock 2511 Blé et produits 2017 2017 Milliers de tonnes -119.0 S Données standardisées

I.a Exploration du fichier population¶

In [6]:
population.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4411 entries, 0 to 4410
Data columns (total 15 columns):
 #   Column                  Non-Null Count  Dtype  
---  ------                  --------------  -----  
 0   Code Domaine            4411 non-null   object 
 1   Domaine                 4411 non-null   object 
 2   Code zone               4411 non-null   int64  
 3   Zone                    4411 non-null   object 
 4   Code Élément            4411 non-null   int64  
 5   Élément                 4411 non-null   object 
 6   Code Produit            4411 non-null   int64  
 7   Produit                 4411 non-null   object 
 8   Code année              4411 non-null   int64  
 9   Année                   4411 non-null   int64  
 10  Unité                   4411 non-null   object 
 11  Valeur                  4411 non-null   float64
 12  Symbole                 4411 non-null   object 
 13  Description du Symbole  4411 non-null   object 
 14  Note                    258 non-null    object 
dtypes: float64(1), int64(5), object(9)
memory usage: 517.0+ KB
In [7]:
population.head(3)
Out[7]:
Code Domaine Domaine Code zone Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur Symbole Description du Symbole Note
0 OA Séries temporelles annuelles 2 Afghanistan 511 Population totale 3010 Population-Estimations 2000 2000 1000 personnes 20779.953 X Sources internationales sûres NaN
1 OA Séries temporelles annuelles 2 Afghanistan 511 Population totale 3010 Population-Estimations 2001 2001 1000 personnes 21606.988 X Sources internationales sûres NaN
2 OA Séries temporelles annuelles 2 Afghanistan 511 Population totale 3010 Population-Estimations 2002 2002 1000 personnes 22600.770 X Sources internationales sûres NaN
In [8]:
population.describe()
Out[8]:
Code zone Code Élément Code Produit Code année Année Valeur
count 4411.000000 4411.0 4411.0 4411.000000 4411.000000 4.411000e+03
mean 132.202902 511.0 3010.0 2009.068238 2009.068238 2.963004e+04
std 75.854840 0.0 0.0 5.481539 5.481539 1.238029e+05
min 1.000000 511.0 3010.0 2000.000000 2000.000000 7.850000e-01
25% 68.000000 511.0 3010.0 2004.000000 2004.000000 3.921890e+02
50% 132.000000 511.0 3010.0 2009.000000 2009.000000 4.764741e+03
75% 195.000000 511.0 3010.0 2014.000000 2014.000000 1.821548e+04
max 299.000000 511.0 3010.0 2018.000000 2018.000000 1.427648e+06
In [9]:
#Observation des variables
print (f' > Symbole : {population["Symbole"].unique()}.')
print (f' > Description du Symbole : {population["Description du Symbole"].unique()}.')
print (f' > Unité : {population["Unité"].unique()}.')
print (f' > Année : {population["Année"].unique()}.')
print (f' > Produit : {population["Produit"].unique()}.')
print (f' > Zone : {population["Zone"].unique()}.')
print (f' > Domaine : {population["Domaine"].unique()}.')
print (f' > Code Domaine : {population["Code Domaine"].unique()}.')
print (f' > Note : {population["Note"].unique()}.')
print (f' > Élément : {population["Élément"].unique()}.')

# Garder Année 2017, Unité, Zone,
 > Symbole : ['X' 'A'].
 > Description du Symbole : ['Sources internationales sûres'
 'Agrégat, peut inclure des données officielles, semi-officielles, estimées ou calculées'].
 > Unité : ['1000 personnes'].
 > Année : [2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
 2014 2015 2016 2017 2018].
 > Produit : ['Population-Estimations'].
 > Zone : ['Afghanistan' 'Afrique du Sud' 'Albanie' 'Algérie' 'Allemagne' 'Andorre'
 'Angola' 'Anguilla' 'Antigua-et-Barbuda' 'Antilles néerlandaises (ex)'
 'Arabie saoudite' 'Argentine' 'Arménie' 'Aruba' 'Australie' 'Autriche'
 'Azerbaïdjan' 'Bahamas' 'Bahreïn' 'Bangladesh' 'Barbade' 'Bélarus'
 'Belgique' 'Belize' 'Bénin' 'Bermudes' 'Bhoutan'
 'Bolivie (État plurinational de)' 'Bonaire, Saint-Eustache et Saba'
 'Bosnie-Herzégovine' 'Botswana' 'Brésil' 'Brunéi Darussalam' 'Bulgarie'
 'Burkina Faso' 'Burundi' 'Cabo Verde' 'Cambodge' 'Cameroun' 'Canada'
 'Chili' 'Chine - RAS de Hong-Kong' 'Chine - RAS de Macao'
 'Chine, continentale' 'Chine, Taiwan Province de' 'Chypre' 'Colombie'
 'Comores' 'Congo' 'Costa Rica' "Côte d'Ivoire" 'Croatie' 'Cuba' 'Curaçao'
 'Danemark' 'Djibouti' 'Dominique' 'Égypte' 'El Salvador'
 'Émirats arabes unis' 'Équateur' 'Érythrée' 'Espagne' 'Estonie'
 'Eswatini' "États-Unis d'Amérique" 'Éthiopie' 'Fédération de Russie'
 'Fidji' 'Finlande' 'France' 'Gabon' 'Gambie' 'Géorgie' 'Ghana'
 'Gibraltar' 'Grèce' 'Grenade' 'Groenland' 'Guadeloupe' 'Guam' 'Guatemala'
 'Guinée' 'Guinée équatoriale' 'Guinée-Bissau' 'Guyana' 'Guyane française'
 'Haïti' 'Honduras' 'Hongrie' 'Île de Man' 'Îles Anglo-Normandes'
 'Îles Caïmanes' 'Îles Cook' 'Îles Falkland (Malvinas)' 'Îles Féroé'
 'Îles Mariannes du Nord' 'Îles Marshall' 'Îles Salomon'
 'Îles Turques-et-Caïques' 'Îles Vierges américaines'
 'Îles Vierges britanniques' 'Îles Wallis-et-Futuna' 'Inde' 'Indonésie'
 "Iran (République islamique d')" 'Iraq' 'Irlande' 'Islande' 'Israël'
 'Italie' 'Jamaïque' 'Japon' 'Jordanie' 'Kazakhstan' 'Kenya'
 'Kirghizistan' 'Kiribati' 'Koweït' 'Lesotho' 'Lettonie' 'Liban' 'Libéria'
 'Libye' 'Liechtenstein' 'Lituanie' 'Luxembourg' 'Macédoine du Nord'
 'Madagascar' 'Malaisie' 'Malawi' 'Maldives' 'Mali' 'Malte' 'Maroc'
 'Martinique' 'Maurice' 'Mauritanie' 'Mayotte' 'Mexique'
 'Micronésie (États fédérés de)' 'Monaco' 'Mongolie' 'Monténégro'
 'Montserrat' 'Mozambique' 'Myanmar' 'Namibie' 'Nauru' 'Népal' 'Nicaragua'
 'Niger' 'Nigéria' 'Nioué' 'Norvège' 'Nouvelle-Calédonie'
 'Nouvelle-Zélande' 'Oman' 'Ouganda' 'Ouzbékistan' 'Pakistan' 'Palaos'
 'Palestine' 'Panama' 'Papouasie-Nouvelle-Guinée' 'Paraguay' 'Pays-Bas'
 'Pérou' 'Philippines' 'Pologne' 'Polynésie française' 'Porto Rico'
 'Portugal' 'Qatar' 'République arabe syrienne'
 'République centrafricaine' 'République de Corée' 'République de Moldova'
 'République démocratique du Congo'
 'République démocratique populaire lao' 'République dominicaine'
 'République populaire démocratique de Corée'
 'République-Unie de Tanzanie' 'Réunion' 'Roumanie'
 "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord" 'Rwanda'
 'Sahara occidental' 'Saint-Barthélemy'
 'Sainte-Hélène, Ascension et Tristan da Cunha' 'Sainte-Lucie'
 'Saint-Kitts-et-Nevis' 'Saint-Marin' 'Saint-Martin (partie française)'
 'Saint-Pierre-et-Miquelon' 'Saint-Siège'
 'Saint-Vincent-et-les Grenadines' 'Samoa' 'Samoa américaines'
 'Sao Tomé-et-Principe' 'Sénégal' 'Serbie' 'Serbie-et-Monténégro'
 'Seychelles' 'Sierra Leone' 'Singapour'
 'Sint Maarten  (partie néerlandaise)' 'Slovaquie' 'Slovénie' 'Somalie'
 'Soudan' 'Soudan (ex)' 'Soudan du Sud' 'Sri Lanka' 'Suède' 'Suisse'
 'Suriname' 'Tadjikistan' 'Tchad' 'Tchéquie' 'Thaïlande' 'Timor-Leste'
 'Togo' 'Tokélaou' 'Tonga' 'Trinité-et-Tobago' 'Tunisie' 'Turkménistan'
 'Turquie' 'Tuvalu' 'Ukraine' 'Uruguay' 'Vanuatu'
 'Venezuela (République bolivarienne du)' 'Viet Nam' 'Yémen' 'Zambie'
 'Zimbabwe'].
 > Domaine : ['Séries temporelles annuelles'].
 > Code Domaine : ['OA'].
 > Note : [nan
 'UNDESA, Population Division – World Population Prospects, the 2017 Revision'].
 > Élément : ['Population totale'].
In [10]:
#Detection des doublons 
population.loc[population.duplicated(keep=False),:]
Out[10]:
Code Domaine Domaine Code zone Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur Symbole Description du Symbole Note
In [11]:
#detection des valeurs manquantes 
print(population.isnull().sum())
Code Domaine                 0
Domaine                      0
Code zone                    0
Zone                         0
Code Élément                 0
Élément                      0
Code Produit                 0
Produit                      0
Code année                   0
Année                        0
Unité                        0
Valeur                       0
Symbole                      0
Description du Symbole       0
Note                      4153
dtype: int64
  • Toute les données sont renseignés excepté Note(sans importance)

  • Aucune modification sur le fichier population

I.b Exploration du fichier dispo_alim¶

In [12]:
dispo_alim.head(3)
Out[12]:
Code Domaine Domaine Code zone Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur Symbole Description du Symbole
0 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5511 Production 2511 Blé et produits 2017 2017 Milliers de tonnes 4281.0 S Données standardisées
1 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5611 Importations - Quantité 2511 Blé et produits 2017 2017 Milliers de tonnes 2302.0 S Données standardisées
2 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5072 Variation de stock 2511 Blé et produits 2017 2017 Milliers de tonnes -119.0 S Données standardisées
In [13]:
dispo_alim.info() 
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 176600 entries, 0 to 176599
Data columns (total 14 columns):
 #   Column                  Non-Null Count   Dtype  
---  ------                  --------------   -----  
 0   Code Domaine            176600 non-null  object 
 1   Domaine                 176600 non-null  object 
 2   Code zone               176600 non-null  int64  
 3   Zone                    176600 non-null  object 
 4   Code Élément            176600 non-null  int64  
 5   Élément                 176600 non-null  object 
 6   Code Produit            176600 non-null  int64  
 7   Produit                 176600 non-null  object 
 8   Code année              176600 non-null  int64  
 9   Année                   176600 non-null  int64  
 10  Unité                   176600 non-null  object 
 11  Valeur                  176600 non-null  float64
 12  Symbole                 176600 non-null  object 
 13  Description du Symbole  176600 non-null  object 
dtypes: float64(1), int64(5), object(8)
memory usage: 18.9+ MB
In [14]:
dispo_alim.describe()
Out[14]:
Code zone Code Élément Code Produit Code année Année Valeur
count 176600.000000 176600.000000 176600.000000 176600.0 176600.0 176600.000000
mean 125.474740 3810.052894 2628.778545 2017.0 2017.0 210.554918
std 72.941699 2211.790089 91.993247 0.0 0.0 4762.047787
min 1.000000 645.000000 2511.000000 2017.0 2017.0 -10388.000000
25% 63.000000 684.000000 2556.000000 2017.0 2017.0 0.000000
50% 120.000000 5142.000000 2612.000000 2017.0 2017.0 0.120000
75% 188.000000 5301.000000 2732.000000 2017.0 2017.0 8.462500
max 276.000000 5911.000000 2899.000000 2017.0 2017.0 758548.000000

1 - une valeur negative détectée¶

2 - Année 2017 uniquement¶

In [15]:
#confirmation de l'année unique 
print (f' > Année : {dispo_alim["Année"].unique()}.')
 > Année : [2017].
In [16]:
#Affichage des valeur negatives 
dispo_alim.loc[dispo_alim["Valeur"] <0,:]
# ce sont les variations de stock qui sont negatives, cela est normal. 
Out[16]:
Code Domaine Domaine Code zone Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur Symbole Description du Symbole
2 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5072 Variation de stock 2511 Blé et produits 2017 2017 Milliers de tonnes -119.0 S Données standardisées
43 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5072 Variation de stock 2514 Maïs et produits 2017 2017 Milliers de tonnes -21.0 S Données standardisées
70 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5072 Variation de stock 2517 Millet et produits 2017 2017 Milliers de tonnes -1.0 S Données standardisées
110 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5072 Variation de stock 2535 Ignames 2017 2017 Milliers de tonnes -1.0 S Données standardisées
169 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5072 Variation de stock 2546 Haricots 2017 2017 Milliers de tonnes -33.0 S Données standardisées
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
176003 FBS Nouveaux Bilans Alimentaire 181 Zimbabwe 5072 Variation de stock 2577 Huile de Palme 2017 2017 Milliers de tonnes -1.0 S Données standardisées
176275 FBS Nouveaux Bilans Alimentaire 181 Zimbabwe 5072 Variation de stock 2641 Piments 2017 2017 Milliers de tonnes -1.0 S Données standardisées
176356 FBS Nouveaux Bilans Alimentaire 181 Zimbabwe 5072 Variation de stock 2731 Viande de Bovins 2017 2017 Milliers de tonnes -1.0 S Données standardisées
176379 FBS Nouveaux Bilans Alimentaire 181 Zimbabwe 5072 Variation de stock 2733 Viande de Suides 2017 2017 Milliers de tonnes -1.0 S Données standardisées
176492 FBS Nouveaux Bilans Alimentaire 181 Zimbabwe 5170 Résidus 2848 Lait - Excl Beurre 2017 2017 Milliers de tonnes -2.0 S Données standardisées

2544 rows × 14 columns

Les valeurs négatives correspondent aux variations de stock.

In [17]:
#detection des doublons
dispo_alim.loc[dispo_alim.duplicated(keep=False),:]
#aucun doublons detecté
Out[17]:
Code Domaine Domaine Code zone Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur Symbole Description du Symbole
In [18]:
print (f' > Domaine : {dispo_alim["Domaine"].unique()}.')
dispo_alim['Domaine'].value_counts()
 > Domaine : ['Nouveaux Bilans Alimentaire'].
Out[18]:
Nouveaux Bilans Alimentaire    176600
Name: Domaine, dtype: int64
In [19]:
dispo_alim.head(1)
Out[19]:
Code Domaine Domaine Code zone Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur Symbole Description du Symbole
0 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5511 Production 2511 Blé et produits 2017 2017 Milliers de tonnes 4281.0 S Données standardisées
In [20]:
print (f' > Unité : {dispo_alim["Unité"].unique()}.')
 > Unité : ['Milliers de tonnes' 'kg' 'Kcal/personne/jour' 'g/personne/jour'].
In [21]:
print (f' > Produit	 : {dispo_alim["Produit"].unique()}.')
#cible  : poulet, viande de volailles,
 > Produit	 : ['Blé et produits' 'Riz et produits' 'Orge et produits' 'Maïs et produits'
 'Seigle et produits' 'Avoine' 'Millet et produits' 'Sorgho et produits'
 'Céréales, Autres' 'Pommes de Terre et produits' 'Ignames' 'Racines nda'
 'Sucre, canne' 'Sucre, betterave' 'Sucre Eq Brut' 'Edulcorants Autres'
 'Miel' 'Haricots' 'Pois' 'Légumineuses Autres et produits'
 'Noix et produits' 'Soja' 'Arachides Decortiquees' 'Graines de tournesol'
 'Graines Colza/Moutarde' 'Graines de coton' 'Coco (Incl Coprah)' 'Sésame'
 'Olives' 'Plantes Oleiferes, Autre' 'Huile de Soja' "Huile d'Arachide"
 'Huile de Tournesol' 'Huile de Colza&Moutarde' 'Huile Graines de Coton'
 'Huile de Palmistes' 'Huile de Palme' 'Huile de Coco' 'Huile de Sésame'
 "Huile d'Olive" 'Huile de Son de Riz' 'Huile de Germe de Maïs'
 'Huil Plantes Oleif Autr' 'Tomates et produits' 'Oignons'
 'Légumes, Autres' 'Oranges, Mandarines' 'Citrons & Limes et produits'
 'Pamplemousse et produits' 'Agrumes, Autres' 'Bananes'
 'Pommes et produits' 'Ananas et produits' 'Dattes' 'Raisin'
 'Fruits, Autres' 'Café et produits' 'Feve de Cacao et produits' 'Thé'
 'Poivre' 'Piments' 'Girofles' 'Épices, Autres' 'Vin' 'Bière'
 'Boissons Fermentés' 'Boissons Alcooliques' 'Alcool, non Comestible'
 'Viande de Bovins' "Viande d'Ovins/Caprins" 'Viande de Suides'
 'Viande de Volailles' 'Viande, Autre' 'Abats Comestible' 'Beurre, Ghee'
 'Crème' 'Graisses Animales Crue' 'Oeufs' 'Lait - Excl Beurre'
 'Poissons Eau Douce' 'Aliments pour enfants' 'Miscellanees'
 'Manioc et produits' 'Patates douces' 'Palmistes' 'Bananes plantains'
 'Huiles de Poissons' 'Huiles de Foie de Poisso' 'Perciform'
 'Poissons Pelagiques' 'Poissons Marins, Autres' 'Crustacés'
 'Cephalopodes' 'Mollusques, Autres' 'Animaux Aquatiques Autre'
 'Plantes Aquatiques' 'Sucre non centrifugé' 'Viande de Anim Aquatiq'].
In [22]:
print (f' > Élément : {dispo_alim["Élément"].unique()}.')
 > Élément : ['Production' 'Importations - Quantité' 'Variation de stock'
 'Exportations - Quantité' 'Disponibilité intérieure'
 'Aliments pour animaux' 'Semences' 'Pertes' 'Résidus' 'Nourriture'
 'Disponibilité alimentaire en quantité (kg/personne/an)'
 'Disponibilité alimentaire (Kcal/personne/jour)'
 'Disponibilité de protéines en quantité (g/personne/jour)'
 'Disponibilité de matière grasse en quantité (g/personne/jour)'
 'Traitement' 'Autres utilisations (non alimentaire)'
 'Alimentation pour touristes'].
In [23]:
#creation df poulet uniquement 
df_chicken = dispo_alim.loc[dispo_alim["Produit"] == "Viande de Volailles",["Zone","Élément","Produit","Unité","Valeur"]]
df_chicken
Out[23]:
Zone Élément Produit Unité Valeur
651 Afghanistan Production Viande de Volailles Milliers de tonnes 28.00
652 Afghanistan Importations - Quantité Viande de Volailles Milliers de tonnes 29.00
653 Afghanistan Variation de stock Viande de Volailles Milliers de tonnes 0.00
654 Afghanistan Disponibilité intérieure Viande de Volailles Milliers de tonnes 57.00
655 Afghanistan Pertes Viande de Volailles Milliers de tonnes 2.00
... ... ... ... ... ...
176396 Zimbabwe Nourriture Viande de Volailles Milliers de tonnes 67.00
176397 Zimbabwe Disponibilité alimentaire en quantité (kg/pers... Viande de Volailles kg 4.68
176398 Zimbabwe Disponibilité alimentaire (Kcal/personne/jour) Viande de Volailles Kcal/personne/jour 16.00
176399 Zimbabwe Disponibilité de protéines en quantité (g/pers... Viande de Volailles g/personne/jour 1.59
176400 Zimbabwe Disponibilité de matière grasse en quantité (g... Viande de Volailles g/personne/jour 0.99

2061 rows × 5 columns

In [24]:
# Ouvrir les data chiffré en valeur dans Element, avec zone en index.
chicken_element = df_chicken.pivot_table(index = "Zone", columns =["Élément"], values = "Valeur").reset_index().rename_axis("",axis=1)
chicken_element
Out[24]:
Zone Alimentation pour touristes Aliments pour animaux Autres utilisations (non alimentaire) Disponibilité alimentaire (Kcal/personne/jour) Disponibilité alimentaire en quantité (kg/personne/an) Disponibilité de matière grasse en quantité (g/personne/jour) Disponibilité de protéines en quantité (g/personne/jour) Disponibilité intérieure Exportations - Quantité Importations - Quantité Nourriture Pertes Production Résidus Semences Traitement Variation de stock
0 Afghanistan NaN NaN NaN 5.0 1.53 0.33 0.54 57.0 NaN 29.0 55.0 2.0 28.0 0.0 NaN NaN 0.0
1 Afrique du Sud 0.0 NaN NaN 143.0 35.69 9.25 14.11 2118.0 63.0 514.0 2035.0 83.0 1667.0 0.0 NaN NaN 0.0
2 Albanie NaN NaN NaN 85.0 16.36 6.45 6.26 47.0 0.0 38.0 47.0 NaN 13.0 0.0 NaN NaN 4.0
3 Algérie 0.0 NaN NaN 22.0 6.38 1.50 1.97 277.0 0.0 2.0 264.0 13.0 275.0 0.0 NaN NaN 0.0
4 Allemagne NaN NaN NaN 71.0 19.47 4.16 7.96 1739.0 646.0 842.0 1609.0 NaN 1514.0 -38.0 NaN 167.0 -29.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
167 Émirats arabes unis NaN NaN NaN 147.0 43.47 9.25 14.80 412.0 94.0 433.0 412.0 NaN 48.0 0.0 NaN NaN -26.0
168 Équateur 0.0 NaN NaN 83.0 19.31 6.35 6.15 341.0 0.0 0.0 324.0 17.0 340.0 0.0 NaN NaN -1.0
169 États-Unis d'Amérique NaN NaN 89.0 219.0 55.68 14.83 19.93 18266.0 3692.0 123.0 18100.0 NaN 21914.0 0.0 NaN 77.0 80.0
170 Éthiopie 0.0 NaN NaN 0.0 0.13 0.03 0.04 14.0 NaN 1.0 14.0 1.0 14.0 0.0 NaN NaN 0.0
171 Îles Salomon 0.0 NaN NaN 18.0 4.45 1.31 1.51 3.0 0.0 6.0 3.0 NaN 0.0 0.0 NaN NaN 3.0

172 rows × 18 columns

In [25]:
#selection des colonnes utiles.
#df[['colonne_1', 'colonne_2', 'colonne_3']]
chicken_element = chicken_element[["Zone","Disponibilité alimentaire en quantité (kg/personne/an)","Production","Exportations - Quantité","Importations - Quantité","Nourriture","Pertes"]]
chicken_element
Out[25]:
Zone Disponibilité alimentaire en quantité (kg/personne/an) Production Exportations - Quantité Importations - Quantité Nourriture Pertes
0 Afghanistan 1.53 28.0 NaN 29.0 55.0 2.0
1 Afrique du Sud 35.69 1667.0 63.0 514.0 2035.0 83.0
2 Albanie 16.36 13.0 0.0 38.0 47.0 NaN
3 Algérie 6.38 275.0 0.0 2.0 264.0 13.0
4 Allemagne 19.47 1514.0 646.0 842.0 1609.0 NaN
... ... ... ... ... ... ... ...
167 Émirats arabes unis 43.47 48.0 94.0 433.0 412.0 NaN
168 Équateur 19.31 340.0 0.0 0.0 324.0 17.0
169 États-Unis d'Amérique 55.68 21914.0 3692.0 123.0 18100.0 NaN
170 Éthiopie 0.13 14.0 NaN 1.0 14.0 1.0
171 Îles Salomon 4.45 0.0 0.0 6.0 3.0 NaN

172 rows × 7 columns

In [26]:
#rename pour indiquer les unités
chicken_element = chicken_element.rename(columns={"Disponibilité alimentaire en quantité (kg/personne/an)" : "Poulet_dispo(kg/pers/an)"})
#chicken_element = chicken_element.rename(columns={"Disponibilité intérieure" : "Disponibilité_int_tx1000"})
chicken_element = chicken_element.rename(columns={"Exportations - Quantité" : "Exportations_tonnesX1000"})
chicken_element = chicken_element.rename(columns={"Importations - Quantité" : "Importations_tonnesX1000"})
chicken_element = chicken_element.rename(columns={"Nourriture" : "Nourriture_tonnesX1000"})
chicken_element = chicken_element.rename(columns={"Pertes" : "Pertes_tonnesX1000"})
chicken_element = chicken_element.rename(columns={"Production" : "Productions_tonnesX1000"})
#chicken_element = chicken_element.rename(columns={"Variation de stock" : "Var_stock_tonnesX1000"})

print("tonnesX1000 egale milliers de tonnes")
tonnesX1000 egale milliers de tonnes
In [27]:
chicken_element.head(2)
Out[27]:
Zone Poulet_dispo(kg/pers/an) Productions_tonnesX1000 Exportations_tonnesX1000 Importations_tonnesX1000 Nourriture_tonnesX1000 Pertes_tonnesX1000
0 Afghanistan 1.53 28.0 NaN 29.0 55.0 2.0
1 Afrique du Sud 35.69 1667.0 63.0 514.0 2035.0 83.0
In [28]:
population.head(1)
Out[28]:
Code Domaine Domaine Code zone Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur Symbole Description du Symbole Note
0 OA Séries temporelles annuelles 2 Afghanistan 511 Population totale 3010 Population-Estimations 2000 2000 1000 personnes 20779.953 X Sources internationales sûres NaN
In [29]:
#mise à l'echelle de population
population["population_ajust"] = population['Valeur']*1000
In [30]:
#selection des colonnes utiles 
population = population[['Zone','Année','population_ajust', ]]
population
Out[30]:
Zone Année population_ajust
0 Afghanistan 2000 20779953.0
1 Afghanistan 2001 21606988.0
2 Afghanistan 2002 22600770.0
3 Afghanistan 2003 23680871.0
4 Afghanistan 2004 24726684.0
... ... ... ...
4406 Zimbabwe 2014 13586707.0
4407 Zimbabwe 2015 13814629.0
4408 Zimbabwe 2016 14030331.0
4409 Zimbabwe 2017 14236595.0
4410 Zimbabwe 2018 14438802.0

4411 rows × 3 columns

In [31]:
#selection de 2017 puisque les data ne sont disponible que pour cette année pour disponibilte_alim
population = population.loc[population["Année"] == 2017,['Zone','Année','population_ajust', ]]
population
Out[31]:
Zone Année population_ajust
17 Afghanistan 2017 36296113.0
36 Afrique du Sud 2017 57009756.0
55 Albanie 2017 2884169.0
74 Algérie 2017 41389189.0
93 Allemagne 2017 82658409.0
... ... ... ...
4333 Venezuela (République bolivarienne du) 2017 29402484.0
4352 Viet Nam 2017 94600648.0
4371 Yémen 2017 27834819.0
4390 Zambie 2017 16853599.0
4409 Zimbabwe 2017 14236595.0

236 rows × 3 columns


I.c Optimisation : Jonction des dataFrames¶

In [32]:
chicken_full = pd.merge(population,chicken_element, how = 'left', on = 'Zone', indicator = True)
chicken_full
Out[32]:
Zone Année population_ajust Poulet_dispo(kg/pers/an) Productions_tonnesX1000 Exportations_tonnesX1000 Importations_tonnesX1000 Nourriture_tonnesX1000 Pertes_tonnesX1000 _merge
0 Afghanistan 2017 36296113.0 1.53 28.0 NaN 29.0 55.0 2.0 both
1 Afrique du Sud 2017 57009756.0 35.69 1667.0 63.0 514.0 2035.0 83.0 both
2 Albanie 2017 2884169.0 16.36 13.0 0.0 38.0 47.0 NaN both
3 Algérie 2017 41389189.0 6.38 275.0 0.0 2.0 264.0 13.0 both
4 Allemagne 2017 82658409.0 19.47 1514.0 646.0 842.0 1609.0 NaN both
... ... ... ... ... ... ... ... ... ... ...
231 Venezuela (République bolivarienne du) 2017 29402484.0 20.28 600.0 0.0 25.0 596.0 30.0 both
232 Viet Nam 2017 94600648.0 12.33 918.0 1.0 291.0 1166.0 39.0 both
233 Yémen 2017 27834819.0 8.53 168.0 0.0 78.0 237.0 8.0 both
234 Zambie 2017 16853599.0 3.42 49.0 1.0 12.0 58.0 2.0 both
235 Zimbabwe 2017 14236595.0 4.68 69.0 NaN 6.0 67.0 3.0 both

236 rows × 10 columns

In [33]:
#detection des anomalie de jonction
chicken_full['_merge'].value_counts()
Out[33]:
both          172
left_only      64
right_only      0
Name: _merge, dtype: int64
In [34]:
chicken_full[chicken_full['_merge'] == 'left_only']
Out[34]:
Zone Année population_ajust Poulet_dispo(kg/pers/an) Productions_tonnesX1000 Exportations_tonnesX1000 Importations_tonnesX1000 Nourriture_tonnesX1000 Pertes_tonnesX1000 _merge
5 Andorre 2017 77001.0 NaN NaN NaN NaN NaN NaN left_only
7 Anguilla 2017 14584.0 NaN NaN NaN NaN NaN NaN left_only
9 Antilles néerlandaises (ex) 2017 275186.0 NaN NaN NaN NaN NaN NaN left_only
13 Aruba 2017 105366.0 NaN NaN NaN NaN NaN NaN left_only
18 Bahreïn 2017 1494076.0 NaN NaN NaN NaN NaN NaN left_only
... ... ... ... ... ... ... ... ... ... ...
208 Somalie 2017 14589179.0 NaN NaN NaN NaN NaN NaN left_only
210 Soudan du Sud 2017 10910763.0 NaN NaN NaN NaN NaN NaN left_only
221 Tokélaou 2017 1300.0 NaN NaN NaN NaN NaN NaN left_only
222 Tonga 2017 101998.0 NaN NaN NaN NaN NaN NaN left_only
227 Tuvalu 2017 11370.0 NaN NaN NaN NaN NaN NaN left_only

64 rows × 10 columns

In [35]:
chicken_full = chicken_full[chicken_full['_merge'] == 'both']
In [36]:
chicken_full['_merge'].value_counts()
Out[36]:
both          172
left_only       0
right_only      0
Name: _merge, dtype: int64
In [37]:
chicken_full.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 172 entries, 0 to 235
Data columns (total 10 columns):
 #   Column                    Non-Null Count  Dtype   
---  ------                    --------------  -----   
 0   Zone                      172 non-null    object  
 1   Année                     172 non-null    int64   
 2   population_ajust          172 non-null    float64 
 3   Poulet_dispo(kg/pers/an)  172 non-null    float64 
 4   Productions_tonnesX1000   168 non-null    float64 
 5   Exportations_tonnesX1000  135 non-null    float64 
 6   Importations_tonnesX1000  170 non-null    float64 
 7   Nourriture_tonnesX1000    170 non-null    float64 
 8   Pertes_tonnesX1000        67 non-null     float64 
 9   _merge                    172 non-null    category
dtypes: category(1), float64(7), int64(1), object(1)
memory usage: 13.7+ KB
In [38]:
#suppression de l'indicateur de jonction
chicken_full = chicken_full.drop(columns = '_merge')
chicken_full.head(1)
Out[38]:
Zone Année population_ajust Poulet_dispo(kg/pers/an) Productions_tonnesX1000 Exportations_tonnesX1000 Importations_tonnesX1000 Nourriture_tonnesX1000 Pertes_tonnesX1000
0 Afghanistan 2017 36296113.0 1.53 28.0 NaN 29.0 55.0 2.0

I.d Optimisation : nettoyage¶

Elimination des îles et pays avec nombre faible.

In [39]:
#Visualisation des stock par rapport a prix 


plt.figure(figsize = (26,16))#(- largeur,- hauteur) 

sns.scatterplot (x = chicken_full['population_ajust'],y = chicken_full['Importations_tonnesX1000'])


#afficher le nom des points 
for i, row in chicken_full.iterrows():
    plt.annotate(row['Zone'], (row['population_ajust'], row['Importations_tonnesX1000']), textcoords="offset points", xytext=(0,10), ha='center',)
    

# Ajoutez des labels aux axes et un titre au scatterplot
plt.xlabel('population_ajustée')
plt.ylabel('Importations en milliers de tonnes')
plt.title('Scatterplot avec les noms des pays')

# Affichez le scatterplot avec les noms des pays
plt.grid(True)
plt.show()

    
#plt.rcParams.update({'font.size': 15})#taille police 
In [40]:
df_select_pop = chicken_full.loc[chicken_full['population_ajust'] < 800000,['Zone','population_ajust','Importations_tonnesX1000']]

df_select_pop est un objet modulable qui permet de visualiser quel pays vont être éliminer par leur paramètre de population et importation.

In [41]:
#Visualisation des stock par rapport a prix 


plt.figure(figsize = (26,16))#(- largeur,- hauteur) 

sns.scatterplot (x = df_select_pop['population_ajust'],y = df_select_pop['Importations_tonnesX1000'])


#afficher le nom des points 
for i, row in df_select_pop.iterrows():
    plt.annotate(row['Zone'], (row['population_ajust'], row['Importations_tonnesX1000']), textcoords="offset points", xytext=(0,10), ha='center',)
    

# Ajoutez des labels aux axes et un titre au scatterplot
plt.xlabel('population_ajustée')
plt.ylabel('Importations en milliers de tonnes')
plt.title('pays dont la population est inférieur à 800 000 habitants')

# Affichez le scatterplot avec les noms des pays
plt.grid(True)
plt.show()

    
#plt.rcParams.update({'font.size': 15})#taille police 

le graphique nous la position des pays par rapport au nombre d'habitants, on peut couper à partir de l'Islande (inclue) c'est a dire pays avec plus de 300k d'habitants.

In [42]:
#mise à l'echelle des variables par rapport à leur population :perspective ACP

chicken_full['chicken_for_people(kg)'] = chicken_full['Nourriture_tonnesX1000'] * 1000000 / chicken_full['population_ajust']
chicken_full['Import_personne(kg)'] = chicken_full['Importations_tonnesX1000'] * 1000000 / chicken_full['population_ajust']
chicken_full['Export_personne(kg)'] = chicken_full['Exportations_tonnesX1000'] * 1000000 / chicken_full['population_ajust']
chicken_full['Prod_personne(kg)'] = chicken_full['Productions_tonnesX1000'] * 1000000 / chicken_full['population_ajust']
chicken_full['Pertes_personne(kg)'] = chicken_full['Pertes_tonnesX1000'] * 1000000 / chicken_full['population_ajust']

    

chicken_full.head(2)
Out[42]:
Zone Année population_ajust Poulet_dispo(kg/pers/an) Productions_tonnesX1000 Exportations_tonnesX1000 Importations_tonnesX1000 Nourriture_tonnesX1000 Pertes_tonnesX1000 chicken_for_people(kg) Import_personne(kg) Export_personne(kg) Prod_personne(kg) Pertes_personne(kg)
0 Afghanistan 2017 36296113.0 1.53 28.0 NaN 29.0 55.0 2.0 1.515314 0.798984 NaN 0.771432 0.055102
1 Afrique du Sud 2017 57009756.0 35.69 1667.0 63.0 514.0 2035.0 83.0 35.695645 9.016001 1.105074 29.240609 1.455891
In [43]:
#observation de la difference entre 2 colonnes
differentiel = (chicken_full['Poulet_dispo(kg/pers/an)']-chicken_full['chicken_for_people(kg)']).sum()
print(f" la diffrence entre la variable poulet_dispo et chicken_for_peaple est de ({differentiel}) kg")
 la diffrence entre la variable poulet_dispo et chicken_for_peaple est de (-6.451896748494376) kg

on remarque que la nouvelle colone chicken_for_people est similaire (difference totale de 6.4kg) a dispo_alim (kg/pers/an). elle sera supprimé.

on peut supprimer les colonnes population, importations, exportations(etc..)d'origines puisqu'elles sont mise a l'echelle avec les nouvelles variables.

on pourrait aller chercher d'autres Data de 2017 pour appronfondir la recherche comme des indices energétiques des pays (petrole, elctricité).

In [44]:
#suppresions des colonnes non-échellonés
#elimination des pays moins de 300 000 habitants
chicken_full = chicken_full.loc[chicken_full['population_ajust'] > 300000,['Zone','population_ajust','Poulet_dispo(kg/pers/an)','Export_personne(kg)','Import_personne(kg)','Prod_personne(kg)','Pertes_personne(kg)']]
chicken_full
Out[44]:
Zone population_ajust Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)
0 Afghanistan 36296113.0 1.53 NaN 0.798984 0.771432 0.055102
1 Afrique du Sud 57009756.0 35.69 1.105074 9.016001 29.240609 1.455891
2 Albanie 2884169.0 16.36 0.000000 13.175372 4.507364 NaN
3 Algérie 41389189.0 6.38 0.000000 0.048322 6.644247 0.314092
4 Allemagne 82658409.0 19.47 7.815297 10.186501 18.316346 NaN
... ... ... ... ... ... ... ...
231 Venezuela (République bolivarienne du) 29402484.0 20.28 0.000000 0.850268 20.406439 1.020322
232 Viet Nam 94600648.0 12.33 0.010571 3.076089 9.703950 0.412259
233 Yémen 27834819.0 8.53 0.000000 2.802246 6.035606 0.287410
234 Zambie 16853599.0 3.42 0.059335 0.712014 2.907391 0.118669
235 Zimbabwe 14236595.0 4.68 NaN 0.421449 4.846665 0.210725

159 rows × 7 columns

In [45]:
print(f'il y a {172-159} pays en moins dans le jeu de données')
il y a 13 pays en moins dans le jeu de données
In [46]:
#copie comme point d'ancrage avec population en moins 
chicken_f = chicken_full
In [47]:
chicken_f = chicken_f.drop(columns = ['population_ajust'])
chicken_f.head(1)
Out[47]:
Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)
0 Afghanistan 1.53 NaN 0.798984 0.771432 0.055102
In [48]:
#detection des NaN
print(chicken_f.isnull().sum())
Zone                         0
Poulet_dispo(kg/pers/an)     0
Export_personne(kg)         30
Import_personne(kg)          2
Prod_personne(kg)            4
Pertes_personne(kg)         92
dtype: int64
In [49]:
#zoom sur les Pertes 
chicken_f.loc[chicken_f['Pertes_personne(kg)'].isna(),:]
 
Out[49]:
Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)
2 Albanie 16.36 0.000000 13.175372 4.507364 NaN
4 Allemagne 19.47 7.815297 10.186501 18.316346 NaN
10 Arabie saoudite 43.36 0.302104 21.811912 18.609609 NaN
14 Australie 47.65 1.708385 0.650813 51.617637 NaN
15 Autriche 18.20 8.843637 12.471795 16.780234 NaN
... ... ... ... ... ... ...
223 Trinité-et-Tobago 54.54 0.000000 16.617789 44.073266 NaN
224 Tunisie 17.03 0.349851 0.000000 18.629559 NaN
226 Turquie 20.64 5.288693 0.036984 27.022879 NaN
228 Ukraine 22.62 6.136526 2.719852 27.221002 NaN
229 Uruguay 9.12 0.872945 0.872945 9.602400 NaN

92 rows × 6 columns

In [50]:
df_pertes = chicken_f.loc[chicken_f['Pertes_personne(kg)'].isna(),:]
pourcentage_pertes = len(df_pertes)*100/len(chicken_f)

print(f"les pertes non renseignées représentent {round(pourcentage_pertes,1)}% du total.")
print("Il sera préférable de supprimer la colonne Pertes pour la suite des analyses.") 
les pertes non renseignées représentent 57.9% du total.
Il sera préférable de supprimer la colonne Pertes pour la suite des analyses.
In [51]:
#reserver sur un df les export zéro
df_Export_null =chicken_f.loc[chicken_f['Export_personne(kg)'] == 0,:]
df_Export_null
Out[51]:
Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)
2 Albanie 16.36 0.0 13.175372 4.507364 NaN
3 Algérie 6.38 0.0 0.048322 6.644247 0.314092
6 Angola 10.56 0.0 9.290075 1.408603 0.067076
12 Arménie 16.06 0.0 11.885394 3.735409 0.000000
16 Azerbaïdjan 13.11 0.0 2.742420 10.563395 NaN
23 Belize 25.69 0.0 0.000000 53.224188 NaN
24 Bénin 14.40 0.0 11.006516 1.610710 NaN
30 Botswana 3.39 0.0 1.360495 2.267491 NaN
38 Cameroun 3.16 0.0 0.000000 3.297230 0.162826
42 Chine - RAS de Macao 34.47 0.0 36.942747 4.818619 0.000000
48 Congo 21.53 0.0 20.349483 1.369677 0.000000
50 Côte d'Ivoire 2.53 0.0 0.286445 2.373404 0.122762
60 Équateur 19.31 0.0 0.000000 20.255745 1.012787
64 Eswatini 6.46 0.0 1.778086 5.334258 NaN
68 Fidji 28.02 0.0 3.418963 26.212051 NaN
71 Gabon 29.33 0.0 36.807029 1.937212 0.000000
74 Ghana 7.24 0.0 5.185179 2.060336 NaN
85 Guyana 38.34 0.0 0.000000 39.988545 NaN
98 Îles Salomon 4.45 0.0 9.433384 0.000000 NaN
104 Indonésie 7.19 0.0 0.003779 8.694471 0.426977
106 Iraq 14.95 0.0 12.515718 2.556402 0.133146
108 Islande 29.95 0.0 5.980986 29.904932 NaN
115 Kenya 0.67 0.0 0.000000 0.696918 0.039824
116 Kirghizistan 3.10 0.0 4.038946 1.130905 NaN
119 Lesotho 7.93 0.0 7.171770 0.956236 NaN
122 Libéria 10.67 0.0 10.207931 3.189979 NaN
133 Malte 27.17 0.0 20.551089 9.133817 NaN
136 Maurice 37.93 0.0 1.581654 37.959698 NaN
143 Monténégro 15.98 0.0 12.747724 6.373862 NaN
146 Myanmar 30.37 0.0 0.056198 31.133785 0.842973
150 Nicaragua 21.59 0.0 0.939725 22.396781 NaN
151 Niger 0.94 0.0 0.138874 0.879533 0.046291
152 Nigéria 1.01 0.0 0.000000 1.053055 0.052391
154 Norvège 19.05 0.0 0.377620 19.069823 NaN
158 Ouganda 1.52 0.0 0.000000 1.578950 0.072875
163 Panama 33.82 0.0 4.870009 48.213084 0.487001
177 République de Moldova 16.14 0.0 3.941193 13.301528 NaN
181 République populaire démocratique de Corée 1.62 0.0 0.000000 1.690928 0.039324
186 Rwanda 1.49 0.0 0.000000 1.585849 0.083466
200 Sénégal 4.76 0.0 0.000000 4.993724 0.259414
203 Sierra Leone 3.97 0.0 1.869553 2.270171 0.133539
216 Tchad 0.45 0.0 0.066592 0.399554 0.000000
220 Togo 7.06 0.0 2.078334 5.195835 NaN
223 Trinité-et-Tobago 54.54 0.0 16.617789 44.073266 NaN
231 Venezuela (République bolivarienne du) 20.28 0.0 0.850268 20.406439 1.020322
233 Yémen 8.53 0.0 2.802246 6.035606 0.287410
In [52]:
df_Export_null =chicken_f.loc[chicken_f['Export_personne(kg)'] == 0,:]
pourcentage_exportNull = len(df_Export_null)*100/len(chicken_f)

print(f'On retrouve {len(df_Export_null)} pays parmis les pays a exportation nulle.')
print(f"Ces {len(df_Export_null)} pays représentent {round(pourcentage_exportNull,1)}% du total.")
print("Aucun action pour le moment.") 
On retrouve 46 pays parmis les pays a exportation nulle.
Ces 46 pays représentent 28.9% du total.
Aucun action pour le moment.
In [53]:
#Afficher les Na pour production
chicken_f.loc[chicken_f["Prod_personne(kg)"].isna(),:]
Out[53]:
Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)
55 Djibouti 2.68 NaN 3.177633 NaN NaN
131 Maldives 13.50 NaN 24.173956 NaN NaN
159 Ouzbékistan 1.96 NaN NaN NaN NaN
179 République démocratique populaire lao 10.91 NaN NaN NaN NaN

Les 4 pays sont mal référencé, la production et l'Exportation manquent. Ils seront supprimés

In [54]:
#suppressions de ces 4 pays 
chicken_f = chicken_f.dropna(subset=['Prod_personne(kg)'])
In [55]:
#confirmation de la suppression
chicken_f.loc[chicken_f["Prod_personne(kg)"].isna(),:]
Out[55]:
Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)

I.e Optimisation des données : reconstition des data liées¶

In [56]:
#afficher les valeurs nulls prod
chicken_f.loc[chicken_f['Prod_personne(kg)'] == 0,:]
Out[56]:
Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)
98 Îles Salomon 4.45 0.000000 9.433384 0.0 NaN
126 Luxembourg 18.33 1.689446 18.583906 0.0 NaN
142 Mongolie 2.77 NaN 3.211524 0.0 NaN

On peut reconstituer la data pour la mongolie.

In [57]:
# Remplacement de export Mongolie par un calcul de flux
#diff_importdispo = 
# diff_importdispo# Case de la 142ème ligne
chicken_f.at[142, 'Export_personne(kg)'] = chicken_f.at[142, 'Import_personne(kg)'] - chicken_f.at[142, 'Poulet_dispo(kg/pers/an)'] #
In [58]:
#confirmation de l'operation
chicken_f.loc[chicken_f['Prod_personne(kg)'] == 0,:]
#ok
Out[58]:
Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)
98 Îles Salomon 4.45 0.000000 9.433384 0.0 NaN
126 Luxembourg 18.33 1.689446 18.583906 0.0 NaN
142 Mongolie 2.77 0.441524 3.211524 0.0 NaN
In [59]:
#checkpoint NaN
print(chicken_f.isnull().sum())
Zone                         0
Poulet_dispo(kg/pers/an)     0
Export_personne(kg)         25
Import_personne(kg)          0
Prod_personne(kg)            0
Pertes_personne(kg)         88
dtype: int64
In [60]:
chicken_f.reset_index(inplace = True)
chicken_f.head(10)
Out[60]:
index Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)
0 0 Afghanistan 1.53 NaN 0.798984 0.771432 0.055102
1 1 Afrique du Sud 35.69 1.105074 9.016001 29.240609 1.455891
2 2 Albanie 16.36 0.000000 13.175372 4.507364 NaN
3 3 Algérie 6.38 0.000000 0.048322 6.644247 0.314092
4 4 Allemagne 19.47 7.815297 10.186501 18.316346 NaN
5 6 Angola 10.56 0.000000 9.290075 1.408603 0.067076
6 10 Arabie saoudite 43.36 0.302104 21.811912 18.609609 NaN
7 11 Argentine 42.24 4.711276 0.182078 49.183902 2.412538
8 12 Arménie 16.06 0.000000 11.885394 3.735409 0.000000
9 14 Australie 47.65 1.708385 0.650813 51.617637 NaN
In [61]:
# Remplacement des NaN par zero pour reconstituer les exports
chicken_f[['Pertes_personne(kg)','Import_personne(kg)','Prod_personne(kg)']] = chicken_f[['Pertes_personne(kg)','Import_personne(kg)','Prod_personne(kg)']].fillna(0)
chicken_f
Out[61]:
index Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)
0 0 Afghanistan 1.53 NaN 0.798984 0.771432 0.055102
1 1 Afrique du Sud 35.69 1.105074 9.016001 29.240609 1.455891
2 2 Albanie 16.36 0.000000 13.175372 4.507364 0.000000
3 3 Algérie 6.38 0.000000 0.048322 6.644247 0.314092
4 4 Allemagne 19.47 7.815297 10.186501 18.316346 0.000000
... ... ... ... ... ... ... ...
150 231 Venezuela (République bolivarienne du) 20.28 0.000000 0.850268 20.406439 1.020322
151 232 Viet Nam 12.33 0.010571 3.076089 9.703950 0.412259
152 233 Yémen 8.53 0.000000 2.802246 6.035606 0.287410
153 234 Zambie 3.42 0.059335 0.712014 2.907391 0.118669
154 235 Zimbabwe 4.68 NaN 0.421449 4.846665 0.210725

155 rows × 7 columns

Les NaN ont été remplacé sauf pour Exportation puisqu'un calcul y sera appliqué

In [62]:
print(chicken_f.isna().sum())
index                        0
Zone                         0
Poulet_dispo(kg/pers/an)     0
Export_personne(kg)         25
Import_personne(kg)          0
Prod_personne(kg)            0
Pertes_personne(kg)          0
dtype: int64
In [63]:
#Calcul de l'exportation théorique en soustrayant l'usage et les pertes de la production & importation.
chicken_f.loc[chicken_f['Export_personne(kg)'].isna(),"Export_personne(kg)"] = chicken_f['Prod_personne(kg)']+ chicken_f['Import_personne(kg)']- chicken_f['Poulet_dispo(kg/pers/an)'] - chicken_f['Pertes_personne(kg)']
chicken_f.head(6)
Out[63]:
index Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)
0 0 Afghanistan 1.53 -0.014686 0.798984 0.771432 0.055102
1 1 Afrique du Sud 35.69 1.105074 9.016001 29.240609 1.455891
2 2 Albanie 16.36 0.000000 13.175372 4.507364 0.000000
3 3 Algérie 6.38 0.000000 0.048322 6.644247 0.314092
4 4 Allemagne 19.47 7.815297 10.186501 18.316346 0.000000
5 6 Angola 10.56 0.000000 9.290075 1.408603 0.067076
In [64]:
# suppression des décimales pour les variables reconstitué
chicken_f['Export_personne(kg)'] = chicken_f['Export_personne(kg)'].astype(int)
In [65]:
chicken_f.describe()
Out[65]:
index Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg) Pertes_personne(kg)
count 155.000000 155.000000 155.000000 155.000000 155.000000 155.000000
mean 113.309677 18.652387 3.987097 7.910261 17.117781 0.275410
std 69.384733 14.088799 11.856275 13.756494 17.368882 0.952933
min 0.000000 0.130000 0.000000 0.000000 0.000000 0.000000
25% 51.500000 5.925000 0.000000 0.302263 2.476540 0.000000
50% 113.000000 17.030000 0.000000 2.983716 12.094367 0.000000
75% 167.500000 28.000000 3.000000 9.909292 26.908470 0.113618
max 235.000000 67.390000 90.000000 124.139068 76.299320 10.049517
In [66]:
print(chicken_f.isna().sum())
index                       0
Zone                        0
Poulet_dispo(kg/pers/an)    0
Export_personne(kg)         0
Import_personne(kg)         0
Prod_personne(kg)           0
Pertes_personne(kg)         0
dtype: int64
In [67]:
chicken_f.drop(columns = 'Pertes_personne(kg)', inplace = True )
In [68]:
chicken_f
Out[68]:
index Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg)
0 0 Afghanistan 1.53 0 0.798984 0.771432
1 1 Afrique du Sud 35.69 1 9.016001 29.240609
2 2 Albanie 16.36 0 13.175372 4.507364
3 3 Algérie 6.38 0 0.048322 6.644247
4 4 Allemagne 19.47 7 10.186501 18.316346
... ... ... ... ... ... ...
150 231 Venezuela (République bolivarienne du) 20.28 0 0.850268 20.406439
151 232 Viet Nam 12.33 0 3.076089 9.703950
152 233 Yémen 8.53 0 2.802246 6.035606
153 234 Zambie 3.42 0 0.712014 2.907391
154 235 Zimbabwe 4.68 0 0.421449 4.846665

155 rows × 6 columns

  • Le DF est complet avec des valeurs import theorique calculées.

  • Suppressioon de pertes.

Le Df est prêt a être exploiter

-II Reperage des tendances dominantes¶

1 dimension

II.a Reperage par critères unilateral¶

In [69]:
#Classement des fort  niveau de disponibilite par personne
chicken_dispo_moins = chicken_f.sort_values (by =["Poulet_dispo(kg/pers/an)"], ascending = False).reset_index(drop=True)
chicken_dispo_moins.head(5)
Out[69]:
index Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg)
0 109 Israël 67.39 0 0.000000 76.299320
1 65 États-Unis d'Amérique 55.68 11 0.378363 67.410113
2 223 Trinité-et-Tobago 54.54 0 16.617789 44.073266
3 41 Chine - RAS de Hong-Kong 53.51 90 124.139068 3.284826
4 111 Jamaïque 51.10 0 10.613356 43.822890
In [70]:
#classement des plus gros producteurs (par personne)
chicken_prod_plus = chicken_f.sort_values(by =["Prod_personne(kg)"], ascending = False)
chicken_prod_plus.head(5)
Out[70]:
index Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg)
73 109 Israël 67.39 0 0.000000 76.299320
21 31 Brésil 48.03 20 0.014435 68.328628
48 65 États-Unis d'Amérique 55.68 11 0.378363 67.410113
114 166 Pays-Bas 20.33 83 35.719852 64.624733
117 169 Pologne 30.30 27 1.449154 61.944743
In [71]:
chicken_import_plus = chicken_f.sort_values(by =["Import_personne(kg)"], ascending = False)
chicken_import_plus.head(5)
Out[71]:
index Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg)
29 41 Chine - RAS de Hong-Kong 53.51 90 124.139068 3.284826
12 17 Bahamas 43.17 35 62.867546 15.716886
43 59 Émirats arabes unis 43.47 9 45.640427 5.059447
30 42 Chine - RAS de Macao 34.47 0 36.942747 4.818619
54 71 Gabon 29.33 0 36.807029 1.937212
In [72]:
chicken_import_plus[:5].describe()
Out[72]:
index Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg)
count 5.000000 5.000000 5.000000 5.000000 5.000000
mean 46.000000 40.790000 26.800000 61.279363 6.163398
std 20.469489 9.299452 38.127418 36.706972 5.487329
min 17.000000 29.330000 0.000000 36.807029 1.937212
25% 41.000000 34.470000 0.000000 36.942747 3.284826
50% 42.000000 43.170000 9.000000 45.640427 4.818619
75% 59.000000 43.470000 35.000000 62.867546 5.059447
max 71.000000 53.510000 90.000000 124.139068 15.716886

Le plus gros importateur, comme Hong-Kong, est certainement approvisioné par toute la chine, il serait intéréssant de connaître d'avantage sur les liens commerciaux entres les régions.

II.b Repérage par Projection 2D¶

In [73]:
#Visualisation des stock par rapport a prix 
plt.figure(figsize = (26,16))#(- largeur,- hauteur) 

sns.scatterplot (x = chicken_import_plus['Prod_personne(kg)'],y = chicken_import_plus['Export_personne(kg)'])


#afficher le nom des points 
for i, row in chicken_import_plus.iterrows():
    plt.annotate(row['Zone'], (row['Prod_personne(kg)'], row['Export_personne(kg)']), textcoords="offset points", xytext=(1,9), ha='center',)
    

# Ajoutez des labels aux axes et un titre au scatterplot
plt.xlabel('Production/population')
plt.ylabel('Exportation')
plt.title("Qui produit pour exporter?", fontsize=30)

# Affichez le scatterplot avec les noms des pays
plt.grid(True)
plt.show()

plt.rcParams.update({'font.size': 20})#taille police 

La chine - RAS(region administrative S) de Hong kong produit peu et pourtant export/importe beaucoup.

In [74]:
# reprensation sous forme de boxplot classé #

taille_classe = 20 # taille des classes pour la discrétisation 
groupes = [] # va recevoir les données agrégées à afficher
# on calcule des tranches allant de 0 au solde maximum par paliers de taille taille_classe
tranches = np.arange(0, max(chicken_f['Prod_personne(kg)']), taille_classe)
tranches += taille_classe/2 # on décale les tranches d'une demi taille de classe
indices = np.digitize(chicken_f['Prod_personne(kg)'], tranches) # associe chaque solde à son numéro de classe
In [75]:
for ind, tr in enumerate(tranches): # pour chaque tranche, ind reçoit le numéro de tranche et tr la tranche en question
    Importkg = chicken_f.loc[indices==ind,'Export_personne(kg)'] # sélection des individus de la tranche ind
    if len (Prodkg) > 0:
        g={
            'valeurs': Importkg,'centre_classe': tr-(taille_classe/2),'taille': len(Importkg),
'quartiles': [np.percentile(Importkg,p) for p in [25,50,75]]
        } 
        groupes.append(g)
        
plt.figure(figsize=(10,7))
plt.title("Qui produit pour exporter ?-boxplot classés-", fontsize=17)

# affichage des boxplots
plt.boxplot([g["valeurs"] for g in groupes],
    positions= [g["centre_classe"] for g in groupes], # abscisses des boxplots 
    showfliers= True, # False elimine les outliers
    widths= taille_classe*0.2) # largeur graphique des boxplots
plt.xlabel(f"'Prod_personne(kg)' slott : {taille_classe}")
plt.ylabel('Export_personne(kg)')

#ax.set(xlabel='Importation par population', ylabel='Production par population')

# affichage des effectifs de chaque classe
for g in groupes:
    plt.text(g["centre_classe"],0,"(n={})".format(g["taille"]),horizontalalignment='center',verticalalignment='top')
plt.show()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[75], line 3
      1 for ind, tr in enumerate(tranches): # pour chaque tranche, ind reçoit le numéro de tranche et tr la tranche en question
      2     Importkg = chicken_f.loc[indices==ind,'Export_personne(kg)'] # sélection des individus de la tranche ind
----> 3     if len (Prodkg) > 0:
      4         g={
      5             'valeurs': Importkg,'centre_classe': tr-(taille_classe/2),'taille': len(Importkg),
      6 'quartiles': [np.percentile(Importkg,p) for p in [25,50,75]]
      7         } 
      8         groupes.append(g)

NameError: name 'Prodkg' is not defined

print (f" On remarque 2 types d'exportateurs :

  • Prod faible n=124
  • Prod forte n=30

On remarque les outliers dans chaque classe

In [76]:
#afficher les 2 plus grands outliers visibles 
chicken_f.loc[chicken_f['Export_personne(kg)']>80]
Out[76]:
index Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg)
29 41 Chine - RAS de Hong-Kong 53.51 90 124.139068 3.284826
114 166 Pays-Bas 20.33 83 35.719852 64.624733
In [77]:
#afficher tous les outliers visibles 
chicken_f.loc[chicken_f['Export_personne(kg)']>30]
Out[77]:
index Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg)
12 17 Bahamas 43.17 35 62.867546 15.716886
15 22 Belgique 12.65 57 29.597851 40.543802
29 41 Chine - RAS de Hong-Kong 53.51 90 124.139068 3.284826
114 166 Pays-Bas 20.33 83 35.719852 64.624733

On remarque que la Chine de Hong-kong ne produit pas mais export/import a grande echelle.

In [78]:
#Visualisation des stock par rapport a prix 
plt.figure(figsize = (26,16))#(- largeur,- hauteur) 

sns.scatterplot (x = chicken_f['Prod_personne(kg)'],y = chicken_f['Poulet_dispo(kg/pers/an)'])


#afficher le nom des points 
for i, row in chicken_import_plus.iterrows():
    plt.annotate(row['Zone'], (row['Poulet_dispo(kg/pers/an)'], row['Prod_personne(kg)']), textcoords="offset points", xytext=(0,10), ha='center',)
    

# Ajoutez des labels aux axes et un titre au scatterplot
plt.xlabel('Prod_personne(kg)')
plt.ylabel('Poulet_dispo(kg/pers/an)')
plt.title("Qui produit pour consommer ?", fontsize=30) 

# Affichez le scatterplot avec les noms des pays
plt.grid(True)
plt.show()

La production semble corrélé à la dispobilité alimentaire, on pourrait tracer une droite de regression lineaire.

In [79]:
#initialisation du modele de regression lieaire.
#en fonction de la production on peut predire la disponibilite alimentaire
from scipy import stats
import matplotlib.pyplot as plt


Xreg = chicken_f['Prod_personne(kg)']
#
Yreg = chicken_f['Poulet_dispo(kg/pers/an)']
#intercept,rvalue,pvalue
slope, intercept, r_value, p_value, std_err = stats.linregress(Xreg, Yreg)

#definition de la fonction predictive
def predict(x):
   return slope * x + intercept
In [80]:
plt.figure(figsize = (11,7))#- largeur, -  hauteur 
axes = plt.axes()
plt.xlabel(f"Prod_personne(kg)")
plt.ylabel('Poulet_dispo(kg/pers/an)')
plt.title("Modèle de Regression lineaire de la disponibilite de poulet en fonction de la production locale", fontsize=15) 

axes.grid() # dessiner une grille pour une meilleur lisibilité du graphe
plt.scatter(Xreg,Yreg) # X et Y sont les variables qu'on a extraite dans le paragraphe précédent
fitLine = predict(Xreg)
plt.plot(Xreg, fitLine, c='r')
plt.show()
In [81]:
#  ajouter un astérisque si p_value est inférieur à 0.5#

#Une étoile (*), par exemple, 0.01 ≤ p-value < 0.05 (significatif à un niveau de 0.05)
#Deux étoiles (**), par exemple, 0.001 ≤ p-value < 0.01 (très significatif à un niveau de 0.01)
#Trois étoiles (***), par exemple, p-value < 0.001 (extrêmement significatif)


def p_etoile(p_val):
    if p_val < 0.001:
        p_val = f"{p_val}***"
    elif p_val < 0.01:
        p_val = f"{p_val}**"
    elif p_val < 0.05:
        p_val = f"{p_val}*"
    return p_val  # Retourne p_value inchangé si aucune condition n'est satisfaite



print("ordonné à l'origine:",intercept)
print("pente:",slope)
print("r_value:",r_value) #amelioration par rapport au modele aleatoire 
print("p_value:",p_etoile(p_value))
ordonné à l'origine: 8.352874044581231
pente: 0.6016850617463861
r_value: 0.7417663569981771
p_value: 2.4607313858615645e-28***
In [82]:
#Application de la fonciton predictive
Prediction = 32

print(f'Pour {Prediction}kg de production, le modele de regression lineaire prédit {round(predict(Prediction),1)}kg de poulet disponible à la consommation.') 
Pour 32kg de production, le modele de regression lineaire prédit 27.6kg de poulet disponible à la consommation.

Le modele nous apprend que les producteurs ne le font pas pour exporter mais surtour pour consommer. Les producteurs-exportateurs sont des exeptions. Il pourrait servir de contact pour comparaison de marchandise.

In [83]:
# (Quantile-Quantile plot) test normalité 
import statsmodels.api as sm
sm.qqplot(Xreg, line='s')  # 's' pour une ligne de tendance (distribution normale)
plt.title("QQ Plot")
plt.show()
In [84]:
#calcul residus
import statsmodels.api as sm
model = sm.OLS(Yreg, Xreg).fit()
residuals = model.resid
In [85]:
# graphique de dispersion des résidus en fonction des valeurs prédites
plt.scatter(fitLine, residuals)
plt.xlabel("Valeurs prédites")
plt.ylabel("Résidus")
plt.title("Graphique de dispersion des résidus")

# Ajout  ligne horizontale pour aider controler homoscedasticité
plt.axhline(y=0, color='r', linestyle='--')

# Affichez le graphique
plt.show()

Le paramètre d'homoscedasticité n'est que partiellement respectée. Nécéssite la suppresion d'outliers ce qui n'est pas adapté a notre problématique. le modèle est simplement estimatif.

In [86]:
# reprensation sous forme de boxplot classé #

taille_classe = 5 # taille des classes pour la discrétisation 
groupes = [] # va recevoir les données agrégées à afficher
# on calcule des tranches allant de 0 au solde maximum par paliers de taille taille_classe
tranches = np.arange(0, max(chicken_f['Import_personne(kg)']), taille_classe)
tranches += taille_classe/2 # on décale les tranches d'une demi taille de classe
indices = np.digitize(chicken_f['Import_personne(kg)'], tranches) # associe chaque solde à son numéro de classe
In [87]:
for ind, tr in enumerate(tranches): # pour chaque tranche, ind reçoit le numéro de tranche et tr la tranche en question
    dispokg = chicken_f.loc[indices==ind,'Export_personne(kg)'] # sélection des individus de la tranche ind
    if len (dispokg) > 0:
        g={
            'valeurs': dispokg,'centre_classe': tr-(taille_classe/2),'taille': len(dispokg),
'quartiles': [np.percentile(dispokg,p) for p in [25,50,75]]
        } 
        groupes.append(g)
        
plt.figure(figsize=(10,7))

# affichage des boxplots
plt.boxplot([g["valeurs"] for g in groupes],
    positions= [g["centre_classe"] for g in groupes], # abscisses des boxplots 
    showfliers= True, # False elimine les outliers
    widths= taille_classe*0.2) # largeur graphique des boxplots`
plt.xlabel(f"Import(kg)'taille classe: {taille_classe}")
plt.ylabel('Export')
plt.title("decoupage de l'import/export ?", fontsize=15) 


#ax.set(xlabel='Importation par population', ylabel='Production par population')

# affichage des effectifs de chaque classe
for g in groupes:
    plt.text(g["centre_classe"],0,"(n={})".format(g["taille"]),horizontalalignment='center',verticalalignment='top')
plt.show()
  • on remarque que les pays qui importent peu n'exportent pas. ceux qui importent a partir de 25kg, exportent un peu plus mais cela reste assez expetionnel.
  • 2 outliers detectés avec Production +45kg et +65kg.
In [2178]:
#Les gros importateur
chicken_import_plus.head(12)
Out[2178]:
index Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg)
29 41 Chine - RAS de Hong-Kong 53.51 90 124.139068 3.284826
12 17 Bahamas 43.17 35 62.867546 15.716886
43 59 Émirats arabes unis 43.47 9 45.640427 5.059447
30 42 Chine - RAS de Macao 34.47 0 36.942747 4.818619
54 71 Gabon 29.33 0 36.807029 1.937212
114 166 Pays-Bas 20.33 83 35.719852 64.624733
81 118 Koweït 46.25 0 33.776296 13.806369
137 214 Suriname 31.06 8 31.551492 17.528607
15 22 Belgique 12.65 57 29.597851 40.543802
39 52 Cuba 23.72 6 27.515038 2.557487
109 157 Oman 21.63 3 27.004274 1.500237
40 54 Danemark 28.98 24 23.201961 30.179995

III- PCA : Principal component analysis¶

les bibliothèteques nécessaire deja chargées.

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import seaborn as sns

In [2180]:
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler

from matplotlib.collections import LineCollection

#on charge seaborn
sns.set()

III.a PCA : Initialisation des paramètres¶

In [2181]:
chicken_acp = chicken_f
chicken_acp
Out[2181]:
index Zone Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg)
0 0 Afghanistan 1.53 0 0.798984 0.771432
1 1 Afrique du Sud 35.69 1 9.016001 29.240609
2 2 Albanie 16.36 0 13.175372 4.507364
3 3 Algérie 6.38 0 0.048322 6.644247
4 4 Allemagne 19.47 7 10.186501 18.316346
... ... ... ... ... ... ...
150 231 Venezuela (République bolivarienne du) 20.28 0 0.850268 20.406439
151 232 Viet Nam 12.33 0 3.076089 9.703950
152 233 Yémen 8.53 0 2.802246 6.035606
153 234 Zambie 3.42 0 0.712014 2.907391
154 235 Zimbabwe 4.68 0 0.421449 4.846665

155 rows × 6 columns

In [2182]:
chicken_acp = chicken_acp.set_index('Zone')
In [2183]:
chicken_acp.head(5)
#indexation des zones ok
Out[2183]:
index Poulet_dispo(kg/pers/an) Export_personne(kg) Import_personne(kg) Prod_personne(kg)
Zone
Afghanistan 0 1.53 0 0.798984 0.771432
Afrique du Sud 1 35.69 1 9.016001 29.240609
Albanie 2 16.36 0 13.175372 4.507364
Algérie 3 6.38 0 0.048322 6.644247
Allemagne 4 19.47 7 10.186501 18.316346
In [1738]:
df = chicken_acp 
In [1739]:
#affichage pourcentage manquant
df.isna().mean()
Out[1739]:
Poulet_dispo(kg/pers/an)    0.0
Export_personne(kg)         0.0
Import_personne(kg)         0.0
Prod_personne(kg)           0.0
dtype: float64
In [1740]:
names = df.index
names
Out[1740]:
Index(['Afghanistan', 'Afrique du Sud', 'Albanie', 'Algérie', 'Allemagne',
       'Angola', 'Arabie saoudite', 'Argentine', 'Arménie', 'Australie',
       ...
       'Tunisie', 'Turkménistan', 'Turquie', 'Ukraine', 'Uruguay',
       'Venezuela (République bolivarienne du)', 'Viet Nam', 'Yémen', 'Zambie',
       'Zimbabwe'],
      dtype='object', name='Zone', length=155)
In [1741]:
cols = ["Poulet_dispo(kg/pers/an)","Import_personne(kg)","Export_personne(kg)","Prod_personne(kg)"]
In [1742]:
df = df[cols]
df.head()
Out[1742]:
Poulet_dispo(kg/pers/an) Import_personne(kg) Export_personne(kg) Prod_personne(kg)
Zone
Afghanistan 1.53 0.798984 0 0.771432
Afrique du Sud 35.69 9.016001 1 29.240609
Albanie 16.36 13.175372 0 4.507364
Algérie 6.38 0.048322 0 6.644247
Allemagne 19.47 10.186501 7 18.316346
In [1595]:
#export du fichier 
df.to_csv('df_P9.csv', index= True) 
In [1743]:
#Separation des données, creation du np.array X
X = df.values
X[:5]
Out[1743]:
array([[ 1.53      ,  0.79898363,  0.        ,  0.77143247],
       [35.69      ,  9.0160007 ,  1.        , 29.24060927],
       [16.36      , 13.17537218,  0.        ,  4.50736417],
       [ 6.38      ,  0.0483218 ,  0.        ,  6.64424712],
       [19.47      , 10.18650141,  7.        , 18.31634577]])
In [1744]:
#confirmation de la forme de la matrice 
X.shape
Out[1744]:
(155, 4)
In [1745]:
features = df.columns
features
Out[1745]:
Index(['Poulet_dispo(kg/pers/an)', 'Import_personne(kg)',
       'Export_personne(kg)', 'Prod_personne(kg)'],
      dtype='object')
In [1746]:
#Scaler les données 
#centrer à zero 
scaler = StandardScaler()
In [1747]:
#Fit les données
#fit retient pour chaque colonne moyenne et ecart-type. enregistre les parametre dans l'objet 
scaler.fit(X)
Out[1747]:
StandardScaler()
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.
StandardScaler()
In [1748]:
#transformation
#transform standardisation appliqué en utulisant les parametre de .fit
X_scaled = scaler.transform(X)
X_scaled[:5]
Out[1748]:
array([[-1.21925861, -0.51861535, -0.33737585, -0.94417907],
       [ 1.21322197,  0.08064001, -0.25275893,  0.70022494],
       [-0.16323733,  0.38397705, -0.33737585, -0.72838846],
       [-0.87389764, -0.57336005, -0.33737585, -0.60496027],
       [ 0.05822095,  0.16600296,  0.25494259,  0.06923013]])
In [1749]:
#verification mean à zéro, ecar type (std) à 1:
idx = ["mean", "std"]

pd.DataFrame(X_scaled).describe().round(2).loc[idx, :]
#OK
Out[1749]:
0 1 2 3
mean 0.0 -0.0 -0.0 0.0
std 1.0 1.0 1.0 1.0
In [1750]:
# travaille sur les 4 premieres composantes . 4 car j'ai 4 features. 
n_components = 4
In [1751]:
#instanciation de l'ACP
pca = PCA(n_components = n_components)
In [1752]:
#on l'entraine sur les données scalées
#normalement on prend le nombre de variable = nombre de composante 
pca.fit(X_scaled)
Out[1752]:
PCA(n_components=4)
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.
PCA(n_components=4)
In [1753]:
#Explained variance & screen plot
#variance captée par chaque nouvelle composante 
#Grace à scikit-learn
pca.explained_variance_ratio_
Out[1753]:
array([0.54182463, 0.32632432, 0.12621917, 0.00563188])
In [1754]:
pca.explained_variance_ratio_.sum()
#on explique 
Out[1754]:
0.9999999999999998
In [1755]:
#enregistrement dans une variable 
scree = (pca.explained_variance_ratio_*100).round(1)
#np.round(scree,2)
scree
# PC1 contient toujours un max de variance 
Out[1755]:
array([54.2, 32.6, 12.6,  0.6])
In [1756]:
#afficher les pertes 
scree_cum = scree.cumsum().round()
scree_cum
Out[1756]:
array([ 54.,  87.,  99., 100.])
In [1776]:
# creation d'une variable avec la liste de nos composantes: #pour affichage
x_list = range(1, n_components+1)
list(x_list)
Out[1776]:
[1, 2, 3, 4]

III.b PCA : Inertie & correlation¶

In [1777]:
plt.bar(x_list, scree)
plt.plot(x_list, scree_cum,c="red",marker='o')
plt.xlabel("rang de l'axe d'inertie")
plt.ylabel("pourcentage d'inertie")
plt.title("Eboulis des valeurs propres")
plt.show(block=False)

Les 3 premieres composantes ont capté toute la variance.

In [1778]:
pcs = pca.components_
pcs
Out[1778]:
array([[ 0.56173683,  0.45687995,  0.51233383,  0.46176453],
       [-0.3562918 ,  0.58921554,  0.40647846, -0.6005468 ],
       [-0.53459992, -0.41837428,  0.6480233 ,  0.34529941],
       [-0.52125887,  0.51869906, -0.39032691,  0.55397236]])
In [1779]:
#affichage sous forme Df
pcs = pd.DataFrame(pcs)
pcs
Out[1779]:
0 1 2 3
0 0.561737 0.456880 0.512334 0.461765
1 -0.356292 0.589216 0.406478 -0.600547
2 -0.534600 -0.418374 0.648023 0.345299
3 -0.521259 0.518699 -0.390327 0.553972
In [1780]:
pcs.columns = features
pcs.index = [f"F{i}" for i in x_list]#liste de comprehension pour imbriqué les composantes principales avec x_list.
pcs.round(1)
Out[1780]:
Poulet_dispo(kg/pers/an) Import_personne(kg) Export_personne(kg) Prod_personne(kg)
F1 0.6 0.5 0.5 0.5
F2 -0.4 0.6 0.4 -0.6
F3 -0.5 -0.4 0.6 0.3
F4 -0.5 0.5 -0.4 0.6
In [1781]:
# affichage différent 
pcs.T
Out[1781]:
F1 F2 F3 F4
Poulet_dispo(kg/pers/an) 0.561737 -0.356292 -0.534600 -0.521259
Import_personne(kg) 0.456880 0.589216 -0.418374 0.518699
Export_personne(kg) 0.512334 0.406478 0.648023 -0.390327
Prod_personne(kg) 0.461765 -0.600547 0.345299 0.553972
In [1764]:
#affichage plus visuel 
fig, ax = plt.subplots(figsize=(20, 6))
sns.heatmap(pcs.T, vmin=-1, vmax=1, annot=True, cmap="coolwarm", fmt="0.2f")
Out[1764]:
<Axes: >

III.c PCA : Visualisation dans l'hypersphere¶

Graphe des corrélations

In [1765]:
#x, y = 0,1
In [1788]:
#version  fonction :
def correlation_graph(pca, x_y, features) : 
   
    # 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)
In [1789]:
#Ici on configure le plan factoriel que le veut afficher (0,1) = F1 & F2
x_y = (0,1)
x_y
Out[1789]:
(0, 1)
In [1792]:
correlation_graph(pca, x_y, features)

Le premier plan factoriel est le relativemnt exhaustif, puisque que F1 explique 54.2% de la variance et F2 (32.6%) .

Les points en haut a droites ont un score plutot élevé en import/export.Les points en bas a droites ont un score plutot élevé en production/disponibilité.

On peut finalement y voir une composante synthétique de flux (import/export) et une d'auto-suffisance (prduction et disponibilité alimentaire). Toute positive sur l'axe F1. Il est l'axe d'inertie de notre echantillon.

In [1622]:
#x_y = (2,3)
#correlation_graph(pca, x_y, features)
#inutile d'afficher F3 F4.


III.d PCA : Projection des points dans l'espace factoriel¶

In [1785]:
#
X_proj = pca.transform(X_scaled)
X_proj[:5]
Out[1785]:
array([[-1.5306849 ,  0.55872331,  0.32413899, -0.02481816],
       [ 0.91219636, -0.9080056 , -0.6043325 , -0.10401094],
       [-0.42545802,  0.58470071, -0.54351898,  0.01243724],
       [-1.20505546,  0.19970084,  0.27954487, -0.04531882],
       [ 0.27113201,  0.13912062,  0.08853759, -0.00540198]])
In [1786]:
#verification de x,y
x_y = (0,1)
x_y
Out[1786]:
(0, 1)
In [1787]:
def display_factorial_planes(   X_projected, 
                                x_y, 
                                pca=None, 
                                labels = None,
                                clusters=None, 
                                alpha=1,
                                figsize=[10,8], 
                                marker="." ):
    # 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)

    # 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) : 
        # pour chacun
        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()
In [1800]:
# projection des point en couleur sur le premier plan factoriel 
x_y = [0,1]
figsize=(8,12)
display_factorial_planes(X_proj, x_y, clusters=df['Prod_personne(kg)'],marker="o")
  • Ici est représenté la production, sur le premier plan factoriel. les valeurs hautes demandent une etude au cas par cas.

On peut observer les points sur le 1er plan factoriel pour la production.

In [2058]:
#ajout des labels 
x_y = [0,1]
display_factorial_planes(X_proj, x_y, pca, labels=names, figsize=(10,10),
                         clusters=df['Prod_personne(kg)'],marker="o")

Ce graphique est identique au précedent avec l'ajout des noms des pays en plus.

In [1648]:
# Transferer la pca sur un autre notebook avec pickle

import pickle

with open('pca.pkl', 'wb') as file:
    pickle.dump(pca, file)