Produisez une étude de marché avec Python¶

Notebook 1 : Préparation, Nettoyage et Analyse exploratoire des données¶

1) Préparation et importation des données¶

In [4]:
import numpy as np
import pandas as pd 

2 fichiers csv bruts ont été fournis :

In [6]:
population = pd.read_csv('Population_2000_2018.csv')
disponibiliteAlimentaire = pd.read_csv('DisponibiliteAlimentaire_2017.csv')
In [8]:
population.head(5)
Out[8]:
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
3 OA Séries temporelles annuelles 2 Afghanistan 511 Population totale 3010 Population-Estimations 2003 2003 1000 personnes 23680.871 X Sources internationales sûres NaN
4 OA Séries temporelles annuelles 2 Afghanistan 511 Population totale 3010 Population-Estimations 2004 2004 1000 personnes 24726.684 X Sources internationales sûres NaN

modalité population

In [12]:
print('Élément : ', list(population['Élément'].unique()))
Élément :  ['Population totale']
In [14]:
print('Année : ', list(population['Année'].unique()))
Année :  [2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018]

Colonnes clés : Code zone, Zone (pays), Année, Valeur (pop en milliers de personnes -> convertir en million)

In [17]:
print(population.columns)
Index(['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'],
      dtype='object')
In [19]:
colonnes_a_supprimer = ['Code Domaine','Domaine','Code Élément', 'Élément', 'Code Produit', 'Produit', 'Code année','Unité','Symbole', 'Description du Symbole', 'Note']
df_population = population.drop(columns = colonnes_a_supprimer, errors="ignore")
df_population = df_population.rename (columns={
                        "Zone" : "Pays",
                        "Valeur" : "Population"})
df_population['Population']=df_population['Population']*1000
df_population.head(5)
Out[19]:
Code zone Pays Année Population
0 2 Afghanistan 2000 20779953.0
1 2 Afghanistan 2001 21606988.0
2 2 Afghanistan 2002 22600770.0
3 2 Afghanistan 2003 23680871.0
4 2 Afghanistan 2004 24726684.0
In [21]:
disponibiliteAlimentaire.head(5)
Out[21]:
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
3 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5911 Exportations - Quantité 2511 Blé et produits 2017 2017 Milliers de tonnes 0.0 S Données standardisées
4 FBS Nouveaux Bilans Alimentaire 2 Afghanistan 5301 Disponibilité intérieure 2511 Blé et produits 2017 2017 Milliers de tonnes 6701.0 S Données standardisées

modalité disponibiliteAlimentaire

In [24]:
print('Élément : ', list(disponibiliteAlimentaire['É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']

-> 'Production', Importations - Quantité, 'Exportations - Quantité', Disponibilité alimentaire en quantité (kg/personne/an).
à voir : Aliments pour animaux

In [27]:
print('Produit : ', list(disponibiliteAlimentaire['Produit'].unique()))
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']

-> Oeufs, Viande de Volailles,
pour viande : 'Viande de Bovins', "Viande d'Ovins/Caprins", 'Viande de Suides', 'Viande de Volailles', 'Viande, Autre', 'Abats Comestible'.

A voir : Maïs et produits (base des rations animales), Soja (proteine vegetale essentielle pour alimentation animale), Blé et produits (utilisé en complément). Pour Afrique , il y a le Sorgho qui est très répandu et peut remplacer le maÏs si trop cher mais à voir... (se reférer à "aliments pour animaux")

In [30]:
print('Année : ', list(disponibiliteAlimentaire['Année'].unique()))
Année :  [2017]
In [32]:
print('Unité : ', list(disponibiliteAlimentaire['Unité'].unique()))
Unité :  ['Milliers de tonnes', 'kg', 'Kcal/personne/jour', 'g/personne/jour']

Colonnes clés : Code zone, Zone (pays), Élément, Produit, Année (2017), Valeur + Unité,

In [35]:
print(disponibiliteAlimentaire.columns)
Index(['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'],
      dtype='object')
In [37]:
colonnes_a_supprimer = ['Code Domaine','Domaine','Code Élément', 'Code Produit', 'Code année','Symbole', 'Description du Symbole']
df_disponibiliteAlimentaire = disponibiliteAlimentaire.drop(columns = colonnes_a_supprimer, errors="ignore")
df_disponibiliteAlimentaire = df_disponibiliteAlimentaire.rename (columns={
                        "Zone" : "Pays",
                        "Valeur" : "Disponibilité alimentaire"})
df_disponibiliteAlimentaire.head(5)
Out[37]:
Code zone Pays Élément Produit Année Unité Disponibilité alimentaire
0 2 Afghanistan Production Blé et produits 2017 Milliers de tonnes 4281.0
1 2 Afghanistan Importations - Quantité Blé et produits 2017 Milliers de tonnes 2302.0
2 2 Afghanistan Variation de stock Blé et produits 2017 Milliers de tonnes -119.0
3 2 Afghanistan Exportations - Quantité Blé et produits 2017 Milliers de tonnes 0.0
4 2 Afghanistan Disponibilité intérieure Blé et produits 2017 Milliers de tonnes 6701.0


Je vais ajouter la stabilité politique (critère Politique)

In [42]:
stabilitePolitique = pd.read_csv('FAOSTAT_stabilitePolitique_2017.csv')
In [44]:
stabilitePolitique.head(5)
Out[44]:
Code Domaine Domaine Code zone (FAO) Zone Code Élément Élément Code Produit Produit Code année Année Valeur
0 FS Données de la sécurité alimentaire 2 Afghanistan 6125 Valeur 21032 Stabilité politique et absence de violence/ter... 2017 2017 -2.79
1 FS Données de la sécurité alimentaire 202 Afrique du Sud 6125 Valeur 21032 Stabilité politique et absence de violence/ter... 2017 2017 -0.28
2 FS Données de la sécurité alimentaire 3 Albanie 6125 Valeur 21032 Stabilité politique et absence de violence/ter... 2017 2017 0.37
3 FS Données de la sécurité alimentaire 4 Algérie 6125 Valeur 21032 Stabilité politique et absence de violence/ter... 2017 2017 -0.92
4 FS Données de la sécurité alimentaire 79 Allemagne 6125 Valeur 21032 Stabilité politique et absence de violence/ter... 2017 2017 0.57

Colonnes clés : Code zone (FAO), Zone, Année (2017), Valeur (indice)

In [47]:
print(stabilitePolitique.columns)
Index(['Code Domaine', 'Domaine', 'Code zone (FAO)', 'Zone', 'Code Élément',
       'Élément', 'Code Produit', 'Produit', 'Code année', 'Année', 'Valeur'],
      dtype='object')
In [49]:
colonnes_a_supprimer = ['Code Domaine','Domaine','Code Élément','Élément','Code Produit','Produit','Code année']
df_stabilitePolitique = stabilitePolitique.drop(columns = colonnes_a_supprimer, errors="ignore")
df_stabilitePolitique = df_stabilitePolitique.rename (columns={
                        "Code zone (FAO)" : "Code zone",
                        "Zone" : "Pays",
                        "Valeur" : "Stabilité politique"})
df_stabilitePolitique.head(5)
Out[49]:
Code zone Pays Année Stabilité politique
0 2 Afghanistan 2017 -2.79
1 202 Afrique du Sud 2017 -0.28
2 3 Albanie 2017 0.37
3 4 Algérie 2017 -0.92
4 79 Allemagne 2017 0.57

Je vais ajouter : Le taux de croissance annuelle du Produit Interieur Brut (critère Economique)

In [52]:
croissancePIB = pd.read_csv('FAOSTAT_CroissancePIB_2017.csv')
In [54]:
croissancePIB.head(5)
Out[54]:
Code Domaine Domaine Code zone (FAO) Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur
0 MK Indicateurs macro 2 Afghanistan 6129 Croissance annuelle US$ 22008 Produit Intérieur Brut 2017 2017 % 4.444345
1 MK Indicateurs macro 202 Afrique du Sud 6129 Croissance annuelle US$ 22008 Produit Intérieur Brut 2017 2017 % 17.791964
2 MK Indicateurs macro 3 Albanie 6129 Croissance annuelle US$ 22008 Produit Intérieur Brut 2017 2017 % 9.767331
3 MK Indicateurs macro 4 Algérie 6129 Croissance annuelle US$ 22008 Produit Intérieur Brut 2017 2017 % 6.287893
4 MK Indicateurs macro 79 Allemagne 6129 Croissance annuelle US$ 22008 Produit Intérieur Brut 2017 2017 % 6.368624

Colonnes clés : Code zone (FAO), Zone, Année (2017), Valeur

In [57]:
print(croissancePIB.columns)
Index(['Code Domaine', 'Domaine', 'Code zone (FAO)', 'Zone', 'Code Élément',
       'Élément', 'Code Produit', 'Produit', 'Code année', 'Année', 'Unité',
       'Valeur'],
      dtype='object')
In [59]:
colonnes_a_supprimer = ['Code Domaine','Domaine','Code Élément','Élément','Code Produit','Produit','Code année','Unité']
df_croissancePIB = croissancePIB.drop(columns = colonnes_a_supprimer, errors="ignore")
df_croissancePIB = df_croissancePIB.rename (columns={
                        "Code zone (FAO)" : "Code zone",
                        "Zone" : "Pays",
                        "Valeur" : "taux de croissance du PIB (%)"})
df_croissancePIB.head(5)
Out[59]:
Code zone Pays Année taux de croissance du PIB (%)
0 2 Afghanistan 2017 4.444345
1 202 Afrique du Sud 2017 17.791964
2 3 Albanie 2017 9.767331
3 4 Algérie 2017 6.287893
4 79 Allemagne 2017 6.368624

Je vais ajouter : Le Revenu National Brut par habitant (critère Economique)

In [62]:
rnb_par_hab = pd.read_csv('FAOSTAT_rnb_par_hab_2017.csv')
In [64]:
rnb_par_hab.head(5)
Out[64]:
Code Domaine Domaine Code zone (FAO) Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur
0 MK Indicateurs macro 2 Afghanistan 6119 Valeur US$ par habitant 22011 Revenu national brut 2017 2017 USD 539.263388
1 MK Indicateurs macro 202 Afrique du Sud 6119 Valeur US$ par habitant 22011 Revenu national brut 2017 2017 USD 6429.574062
2 MK Indicateurs macro 3 Albanie 6119 Valeur US$ par habitant 22011 Revenu national brut 2017 2017 USD 4503.239709
3 MK Indicateurs macro 4 Algérie 6119 Valeur US$ par habitant 22011 Revenu national brut 2017 2017 USD 4027.655361
4 MK Indicateurs macro 79 Allemagne 6119 Valeur US$ par habitant 22011 Revenu national brut 2017 2017 USD 45470.601480

Colonnes clés : Code zone (FAO), Zone, Annéé (2017), Valeur

In [67]:
print(rnb_par_hab.columns)
Index(['Code Domaine', 'Domaine', 'Code zone (FAO)', 'Zone', 'Code Élément',
       'Élément', 'Code Produit', 'Produit', 'Code année', 'Année', 'Unité',
       'Valeur'],
      dtype='object')
In [69]:
colonnes_a_supprimer = ['Code Domaine','Domaine','Code Élément','Élément','Code Produit','Produit','Code année','Unité']
df_rnb_par_hab = rnb_par_hab.drop(columns = colonnes_a_supprimer, errors="ignore")
df_rnb_par_hab = df_rnb_par_hab.rename (columns={
                        "Code zone (FAO)" : "Code zone",
                        "Zone" : "Pays",
                        "Valeur" : "RNB/hab (USD)"})
df_rnb_par_hab.head(5)
Out[69]:
Code zone Pays Année RNB/hab (USD)
0 2 Afghanistan 2017 539.263388
1 202 Afrique du Sud 2017 6429.574062
2 3 Albanie 2017 4503.239709
3 4 Algérie 2017 4027.655361
4 79 Allemagne 2017 45470.601480

Je vais ajouter la surface agricole (critère Environnemental)

In [72]:
surfaceAgricole = pd.read_csv('FAOSTAT_superficieAgricole_2017.csv')
In [74]:
surfaceAgricole.head(5)
Out[74]:
Code Domaine Domaine Code zone (FAO) Zone Code Élément Élément Code Produit Produit Code année Année Unité Valeur
0 RL Utilisation des terres 2 Afghanistan 5110 Superficie 6610 Terres agricoles 2017 2017 1000 ha 37910.0000
1 RL Utilisation des terres 202 Afrique du Sud 5110 Superficie 6610 Terres agricoles 2017 2017 1000 ha 96341.0000
2 RL Utilisation des terres 3 Albanie 5110 Superficie 6610 Terres agricoles 2017 2017 1000 ha 1174.2810
3 RL Utilisation des terres 4 Algérie 5110 Superficie 6610 Terres agricoles 2017 2017 1000 ha 41335.1408
4 RL Utilisation des terres 79 Allemagne 5110 Superficie 6610 Terres agricoles 2017 2017 1000 ha 16687.0000

Colonnes clés : Code zone (FAO), Zone, Année (2017), Valeur

In [77]:
print(surfaceAgricole.columns)
Index(['Code Domaine', 'Domaine', 'Code zone (FAO)', 'Zone', 'Code Élément',
       'Élément', 'Code Produit', 'Produit', 'Code année', 'Année', 'Unité',
       'Valeur'],
      dtype='object')
In [79]:
colonnes_a_supprimer = ['Code Domaine', 'Domaine','Code Élément','Élément','Code Produit','Produit','Code année','Unité']
df_surfaceAgricole = surfaceAgricole.drop(columns = colonnes_a_supprimer, errors="ignore")
df_surfaceAgricole = df_surfaceAgricole.rename (columns={
                        "Code zone (FAO)" : "Code zone",
                        "Zone" : "Pays",
                        "Valeur" : "Surface agricole (1000 ha)"})
df_surfaceAgricole.head(5)
Out[79]:
Code zone Pays Année Surface agricole (1000 ha)
0 2 Afghanistan 2017 37910.0000
1 202 Afrique du Sud 2017 96341.0000
2 3 Albanie 2017 1174.2810
3 4 Algérie 2017 41335.1408
4 79 Allemagne 2017 16687.0000

Récapitulatif des (9+1) indicateurs choisis selon critère PESTEL, pour l'année 2017 sauf indication contraire :

POLITIQUE : Stabilité politique
ECONOMIQUE : Taux de croissance annuel du PIB, RNB/hab, TDI (à calculer).
SOCIOCULTUREL : Disponibilité alimentaire de volaille, part de volaille dans la consommation de viande (à calculer), CAGR (2000-2018, à calculer)
TECHNOLOGIQUE : Aliment pour animaux
ENVIRONNEMENTAL : Surface agricole par habitant (à calculer)
LEGAL : cf Site si pays membre (Codex Alimentarius, 188 pays)

https://www.fao.org/fao-who-codexalimentarius/about-codex/members/fr/

https://www.fao.org/4/X9892F/x9892f09.htm

https://www.fao.org/faostat/fr/#data/FS

Jusqu'ici on a : 6 tables -> df_population, df_disponibiliteAlimentaire, df_stabilitePolitique, df_croissancePIB, df_rnb_par_hab, df_surfaceAgricole

2) Nettoyage des données : mettre les données au propre et utilisable¶

CALCUL : Taux de croissance démographique annuel composé (CAGR), 2000-2018

In [88]:
df_population.head(5)
Out[88]:
Code zone Pays Année Population
0 2 Afghanistan 2000 20779953.0
1 2 Afghanistan 2001 21606988.0
2 2 Afghanistan 2002 22600770.0
3 2 Afghanistan 2003 23680871.0
4 2 Afghanistan 2004 24726684.0
In [90]:
# extraction des populations en 2000 et 2018
pop_2000= df_population[df_population["Année"]==2000][["Code zone","Pays","Population"]].rename(columns={"Population": "Pop_2000"})
pop_2018= df_population[df_population["Année"]==2018][["Code zone","Pays","Population"]].rename(columns={"Population": "Pop_2018"})

#jointure sur les pays
df_croissancePopulation = pd.merge(pop_2000, pop_2018, on=["Code zone"])
df_croissancePopulation = df_croissancePopulation.drop(columns=["Pays_y"])
df_croissancePopulation = df_croissancePopulation.rename(columns={"Pays_x":"Pays"})

#calcul croissance totale (%)
df_croissancePopulation["Croissance_totale (%), 2000-2018"]=((df_croissancePopulation["Pop_2018"]-df_croissancePopulation["Pop_2000"])/df_croissancePopulation["Pop_2000"])*100

#calcul CAGR (%)
nb_années= 2018-2000
df_croissancePopulation["CAGR (%/an), 2000-2018"]=(((df_croissancePopulation["Pop_2018"]/df_croissancePopulation["Pop_2000"]) ** (1/nb_années))-1)*100

#resultat
df_croissancePopulation.head(5)
Out[90]:
Code zone Pays Pop_2000 Pop_2018 Croissance_totale (%), 2000-2018 CAGR (%/an), 2000-2018
0 2 Afghanistan 20779953.0 37171921.0 78.883566 3.283677
1 202 Afrique du Sud 44967708.0 57792518.0 28.520044 1.403732
2 3 Albanie 3129243.0 2882740.0 -7.877400 -0.454795
3 4 Algérie 31042235.0 42228408.0 36.035334 1.724390
4 79 Allemagne 81400882.0 83124418.0 2.117343 0.116470
In [92]:
df_check = pd.merge(pop_2000,pop_2018, on="Code zone", how="inner")

#chercher diff de noms 
diff = df_check[df_check["Pays_x"] != df_check["Pays_y"]][["Code zone","Pays_x","Pays_y"]]
print(diff.head())
Empty DataFrame
Columns: [Code zone, Pays_x, Pays_y]
Index: []

CALCUL : Taux de dependances aux importations (TDI), pour les produits avicoles (Viande de Volailles et Oeufs), 2017

In [95]:
df_disponibiliteAlimentaire.head(5)
Out[95]:
Code zone Pays Élément Produit Année Unité Disponibilité alimentaire
0 2 Afghanistan Production Blé et produits 2017 Milliers de tonnes 4281.0
1 2 Afghanistan Importations - Quantité Blé et produits 2017 Milliers de tonnes 2302.0
2 2 Afghanistan Variation de stock Blé et produits 2017 Milliers de tonnes -119.0
3 2 Afghanistan Exportations - Quantité Blé et produits 2017 Milliers de tonnes 0.0
4 2 Afghanistan Disponibilité intérieure Blé et produits 2017 Milliers de tonnes 6701.0
In [97]:
df_disponibiliteAlimentaire.isna().sum()
Out[97]:
Code zone                    0
Pays                         0
Élément                      0
Produit                      0
Année                        0
Unité                        0
Disponibilité alimentaire    0
dtype: int64
In [99]:
#filtre les PRODUIT avicoles + je garde les ELEMENT utiles à ma formule tdi
produits_avicoles=["Viande de Volailles", "Oeufs"]
elmt_tdi=["Production", "Importations - Quantité", "Exportations - Quantité"]
df_tdi= df_disponibiliteAlimentaire[df_disponibiliteAlimentaire["Produit"].isin(produits_avicoles)& df_disponibiliteAlimentaire["Élément"].isin(elmt_tdi)]

#pivot pour que chaque element soit une colonne à part entière (lisibilité de lecture, info direct pour chaque pays)
df_tdi= df_tdi.pivot_table(
    index = ["Code zone","Pays"],
    columns = "Élément",
    values = "Disponibilité alimentaire",   
    aggfunc="sum" #sum volaille et oeufs
).reset_index()

#calcul du denominateur  = production + importation - exportation
df_tdi["denominateur"]=(
    df_tdi["Production"].fillna(0) + df_tdi["Importations - Quantité"].fillna(0) - df_tdi["Exportations - Quantité"].fillna(0)
)

#calcul du TDI (selon définition de FAO) 
df_tdi["TDI_avicole (%)"]= np.where(
    df_tdi["denominateur"]>0, 
    (df_tdi["Importations - Quantité"].fillna(0) / df_tdi["denominateur"])*100,
    np.nan
).round(2)

#suppression colonne denominateur 
df_tdi= df_tdi.drop(columns=["denominateur"])

#resultat
df_tdi.head(5)
Out[99]:
Élément Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
0 1 Arménie 0.0 36.0 48.0 42.86
1 2 Afghanistan 0.0 83.0 48.0 63.36
2 3 Albanie 1.0 38.0 64.0 37.62
3 4 Algérie 0.0 2.0 665.0 0.30
4 7 Angola 0.0 300.0 47.0 86.46
In [101]:
df_tdi.columns.name = None
df_tdi.head(5)
Out[101]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
0 1 Arménie 0.0 36.0 48.0 42.86
1 2 Afghanistan 0.0 83.0 48.0 63.36
2 3 Albanie 1.0 38.0 64.0 37.62
3 4 Algérie 0.0 2.0 665.0 0.30
4 7 Angola 0.0 300.0 47.0 86.46
In [103]:
df_tdi.isna().sum()
Out[103]:
Code zone                   0
Pays                        0
Exportations - Quantité    26
Importations - Quantité     0
Production                  2
TDI_avicole (%)             0
dtype: int64
In [105]:
missing_rows = df_tdi[df_tdi.isna().any(axis=1)]
print(missing_rows)
     Code zone                             Pays  Exportations - Quantité  \
9           12                          Bahamas                      NaN   
11          16                       Bangladesh                      NaN   
21          35                       Cabo Verde                      NaN   
22          37        République centrafricaine                      NaN   
30          49                             Cuba                      NaN   
46          72                         Djibouti                      NaN   
49          75                           Gambie                      NaN   
53          83                         Kiribati                      NaN   
55          86                          Grenade                      NaN   
57          90                           Guinée                      NaN   
59          93                            Haïti                      NaN   
92         132                         Maldives                      NaN   
95         136                       Mauritanie                      NaN   
98         141                         Mongolie                      NaN   
100        144                       Mozambique                      NaN   
103        149                            Népal                      NaN   
105        153               Nouvelle-Calédonie                      NaN   
107        155                          Vanuatu                      NaN   
121        175                    Guinée-Bissau                      NaN   
122        176                      Timor-Leste                      NaN   
129        191  Saint-Vincent-et-les Grenadines                      NaN   
130        193             Sao Tomé-et-Principe                      NaN   
143        213                     Turkménistan                      NaN   
157        233                     Burkina Faso                      NaN   
161        238                         Éthiopie                      NaN   
169        276                           Soudan                      NaN   

     Importations - Quantité  Production  TDI_avicole (%)  
9                       26.0         7.0            78.79  
11                       0.0       942.0             0.00  
21                      13.0         4.0            76.47  
22                       5.0        10.0            33.33  
30                     313.0       141.0            68.94  
46                       4.0         NaN           100.00  
49                      20.0         3.0            86.96  
53                       1.0         1.0            50.00  
55                       7.0         2.0            77.78  
57                      37.0        39.0            48.68  
59                      91.0        14.0            86.67  
92                      21.0         NaN           100.00  
95                      29.0        11.0            72.50  
98                      18.0         5.0            78.26  
100                     36.0       145.0            19.89  
103                      0.0       126.0             0.00  
105                      9.0         3.0            75.00  
107                      4.0         2.0            66.67  
121                      6.0         4.0            60.00  
122                     11.0         2.0            84.62  
129                      9.0         1.0            90.00  
130                      2.0         1.0            66.67  
143                      9.0        71.0            11.25  
157                      0.0       104.0             0.00  
161                      1.0        69.0             1.43  
169                      3.0       123.0             2.38  
In [107]:
pourcentage_nan = df_tdi.isna().sum()/len(df_tdi) *100
print(pourcentage_nan)
Code zone                   0.000000
Pays                        0.000000
Exportations - Quantité    15.294118
Importations - Quantité     0.000000
Production                  1.176471
TDI_avicole (%)             0.000000
dtype: float64

Memo :
Les NAN sont remplacés par 0 lors du calucul du tdi
26 pays avec données totalement manquantes sur les 2 produits (très rares, et pour exportation),
de plus les pays concernés par ces manques sont globalement des petits marchés ou peu stratégiques donc impact limité sur l'analyse.

CALCUL : Part avicole (volailles + oeufs) dans la consommation de viande et oeufs (%), 2017

In [111]:
#filtre sur les produits 
produits_avicoles=["Viande de Volailles", "Oeufs"]
produits_viandes_oeufs= ["Viande de Bovins", "Viande d'Ovins/Caprins", "Viande de Suides", "Viande de Volailles", "Viande, Autre", "Oeufs"] #je ne compte pas les abats comestibles car ça peut provenir de toutes viandes confondues ( mouton, poulet etc.).
elmt= ["Disponibilité alimentaire en quantité (kg/personne/an)"]
part_avicole= df_disponibiliteAlimentaire[df_disponibiliteAlimentaire["Produit"].isin(produits_viandes_oeufs)& df_disponibiliteAlimentaire["Élément"].isin(elmt)]

#pivot pour que les produits soient en colonnes pour chaque pays
part_avicole=part_avicole.pivot_table(
    index = ["Code zone","Pays"],
    columns = "Produit",
    values = "Disponibilité alimentaire",   
).reset_index()

#calcul du numerateur et denominateur 
num = part_avicole["Oeufs"] + part_avicole["Viande de Volailles"]
den = part_avicole[produits_viandes_oeufs].sum(axis=1) #je fais la somme horizontale des valeurs de tous les produits , par ligne : total par pays

df_part_avicole= pd.DataFrame({
    "Code zone": part_avicole["Code zone"],
    "Pays": part_avicole["Pays"],
    "Quantité de produits avicoles (kg/hab/an) ": part_avicole[produits_avicoles].sum(axis=1),
    "Part avicole (%)": np.where(den>0, (num/den) * 100, np.nan).round(2)
}  ).sort_values("Part avicole (%)",ascending=False)


#part_avicole.head(5)
df_part_avicole.head(5)
Out[111]:
Code zone Pays Quantité de produits avicoles (kg/hab/an) Part avicole (%)
23 38 Sri Lanka 12.05 90.60
74 109 Jamaïque 53.08 87.10
68 103 Iraq 24.39 85.58
58 91 Guyana 40.20 85.39
132 194 Arabie saoudite 49.92 82.27
In [113]:
pourcentage_nan = df_part_avicole.isna().sum()/len(df_part_avicole) *100
print(pourcentage_nan)
Code zone                                     0.0
Pays                                          0.0
Quantité de produits avicoles (kg/hab/an)     0.0
Part avicole (%)                              0.0
dtype: float64

CALCUL : Surface agricole / hab

In [116]:
df_surfaceAgricole.head(5)
Out[116]:
Code zone Pays Année Surface agricole (1000 ha)
0 2 Afghanistan 2017 37910.0000
1 202 Afrique du Sud 2017 96341.0000
2 3 Albanie 2017 1174.2810
3 4 Algérie 2017 41335.1408
4 79 Allemagne 2017 16687.0000
In [118]:
#je filtre pop sur 2017 et refais une table pour surface sans annee 
pop_2017= df_population[df_population["Année"]==2017][["Code zone","Pays","Population"]].rename(columns={"Population": "Pop_2017"})
sur_2017 = df_surfaceAgricole.drop(columns=["Année"])

#Attention surface Agricole est en 1000 ha -> convertir en ha
sur_2017["Surface agricole (ha) "]= sur_2017["Surface agricole (1000 ha)"]*1000


#jointure (left join car je garde sur_2017 et je la modifie) 
df_surfaceAgricole_complet = pd.merge(sur_2017, pop_2017, on="Code zone", how="left", suffixes=("_surfaceAgricole","_population")) 


#calcul surface agricole / hab 
df_surfaceAgricole_complet["Surface agricole par hab (ha/hab)"]=(df_surfaceAgricole_complet["Surface agricole (ha) "] / df_surfaceAgricole_complet["Pop_2017"]).round(4)
df_surfaceAgricole_complet = df_surfaceAgricole_complet.drop(columns=["Surface agricole (1000 ha)"])
df_surfaceAgricole_complet.head(5)
Out[118]:
Code zone Pays_surfaceAgricole Surface agricole (ha) Pays_population Pop_2017 Surface agricole par hab (ha/hab)
0 2 Afghanistan 37910000.0 Afghanistan 36296113.0 1.0445
1 202 Afrique du Sud 96341000.0 Afrique du Sud 57009756.0 1.6899
2 3 Albanie 1174281.0 Albanie 2884169.0 0.4071
3 4 Algérie 41335140.8 Algérie 41389189.0 0.9987
4 79 Allemagne 16687000.0 Allemagne 82658409.0 0.2019
In [120]:
df_surfaceAgricole_complet.isna().sum()
Out[120]:
Code zone                            0
Pays_surfaceAgricole                 0
Surface agricole (ha)                0
Pays_population                      2
Pop_2017                             2
Surface agricole par hab (ha/hab)    2
dtype: int64
In [122]:
pourcentage_nan = df_surfaceAgricole_complet.isna().sum()/len(df_surfaceAgricole_complet) *100
print(pourcentage_nan)
Code zone                            0.000000
Pays_surfaceAgricole                 0.000000
Surface agricole (ha)                0.000000
Pays_population                      0.881057
Pop_2017                             0.881057
Surface agricole par hab (ha/hab)    0.881057
dtype: float64

il y a 2 pays presents dans la table surface agricole mais pas dans dans la table population :

In [125]:
missing_rows = df_surfaceAgricole_complet[df_surfaceAgricole_complet.isna().any(axis=1)]
print(missing_rows)
    Code zone Pays_surfaceAgricole  Surface agricole (ha)  Pays_population  \
39        351                Chine             522997100.0             NaN   
87        161          Île Norfolk                  1000.0             NaN   

    Pop_2017  Surface agricole par hab (ha/hab)  
39       NaN                                NaN  
87       NaN                                NaN  
In [127]:
df_surfaceAgricole_complet[df_surfaceAgricole_complet["Code zone"]==41]
Out[127]:
Code zone Pays_surfaceAgricole Surface agricole (ha) Pays_population Pop_2017 Surface agricole par hab (ha/hab)
41 41 Chine, continentale 522199000.0 Chine, continentale 1.421022e+09 0.3675

La Chine n'est pas perdue en réalité dans surfaceAgricole_complet car elle est présente en doublons implicite via "La Chine Continentale".
Quant à Île Norfolk, il s'agit d'un petit marché donc non pertinent à retenir.
Les deux seront nettoyés automatiquement de notre table finale car données manquantes en TDI avicole notamment.

CALCUL : aliment pour animaux

In [131]:
#filtre aliment pour animaux 

df_aliment_pour_animaux= df_disponibiliteAlimentaire.loc[df_disponibiliteAlimentaire["Élément"]=="Aliments pour animaux",["Code zone", "Pays", "Produit","Unité","Disponibilité alimentaire"]]
df_aliment_pour_animaux.head()
Out[131]:
Code zone Pays Produit Unité Disponibilité alimentaire
5 2 Afghanistan Blé et produits Milliers de tonnes 76.0
18 2 Afghanistan Riz et produits Milliers de tonnes 0.0
32 2 Afghanistan Orge et produits Milliers de tonnes 67.0
46 2 Afghanistan Maïs et produits Milliers de tonnes 111.0
59 2 Afghanistan Seigle et produits Milliers de tonnes 0.0
In [133]:
print('Produit : ', list(df_aliment_pour_animaux['Produit'].unique()))
Produit :  ['Blé et produits', 'Riz et produits', 'Orge et produits', 'Maïs et produits', 'Seigle et produits', 'Sorgho et produits', 'Céréales, Autres', 'Sucre, canne', 'Sucre, betterave', 'Pois', 'Légumineuses Autres et produits', 'Arachides Decortiquees', 'Graines Colza/Moutarde', 'Coco (Incl Coprah)', 'Plantes Oleiferes, Autre', 'Raisin', 'Oeufs', 'Lait - Excl Beurre', 'Avoine', 'Millet et produits', 'Pommes de Terre et produits', 'Patates douces', 'Ignames', 'Racines nda', 'Edulcorants Autres', 'Haricots', 'Soja', 'Graines de tournesol', 'Graines de coton', 'Sésame', 'Huil Plantes Oleif Autr', 'Légumes, Autres', 'Viande, Autre', 'Abats Comestible', 'Huiles de Poissons', 'Perciform', 'Poissons Pelagiques', 'Poissons Marins, Autres', 'Palmistes', 'Olives', 'Beurre, Ghee', 'Manioc et produits', 'Sucre Eq Brut', 'Huile de Colza&Moutarde', 'Graisses Animales Crue', 'Crustacés', 'Huile de Sésame', 'Poissons Eau Douce', 'Tomates et produits', 'Pommes et produits', 'Girofles', 'Huile de Soja', 'Bananes plantains', 'Bananes', 'Huiles de Foie de Poisso', "Viande d'Ovins/Caprins", 'Cephalopodes', "Huile d'Arachide", 'Huile Graines de Coton', 'Huile de Palmistes', 'Huile de Palme', 'Huile de Coco', 'Sucre non centrifugé', "Huile d'Olive", 'Oranges, Mandarines', 'Dattes', 'Fruits, Autres', 'Feve de Cacao et produits', 'Viande de Bovins', 'Oignons', 'Mollusques, Autres', 'Plantes Aquatiques', 'Miel', 'Noix et produits', 'Huile de Tournesol', 'Citrons & Limes et produits', 'Pamplemousse et produits', 'Agrumes, Autres', 'Ananas et produits', 'Café et produits', 'Thé', 'Poivre', 'Piments', 'Épices, Autres', 'Vin', 'Bière', 'Boissons Fermentés', 'Boissons Alcooliques', 'Alcool, non Comestible', 'Viande de Suides', 'Viande de Volailles', 'Crème', 'Aliments pour enfants', 'Miscellanees']

ALIMENTATION des poules (base avicole, marqueurs d'industrialisation avicole) :
Céréales de base (énergie) : 'Maïs et produits', 'Sorgho et produits', 'Blé et produits'.
Protéagineux/oléagineux (proteine pour les rations) : 'Soja', 'Graines de tournesol', 'Graines Colza/Moutarde'

Ces 6 produits représentent le coeur de l'alimentation avicole INDUSTRIELLE moderne dans le monde. Les autres (riz, manioc, patates douces...) sont utilisés localement mais pas caractéristiques d'une filière avicole structurée.

In [136]:
#produits clés pour l'alimentation avicole industrielle : 
produits_indust_avicole = ['Maïs et produits', 'Sorgho et produits', 'Blé et produits', 'Soja', 'Graines de tournesol', 'Graines Colza/Moutarde']

#filtrer uniquement les aliments pour animaux (element) et produits avicole (produits) : 
df_aliment_avicole_temp = df_aliment_pour_animaux[df_aliment_pour_animaux["Produit"].isin(produits_indust_avicole)][["Code zone","Pays","Produit","Disponibilité alimentaire"]]


#calcul somme dispoAlim de ces produits pour animaux par pays : 
df_aliment_avicole = (df_aliment_avicole_temp.groupby(["Code zone","Pays"], as_index=False)["Disponibilité alimentaire"].sum()
                     )

#unité : Milliers de tonnes 
df_aliment_avicole = df_aliment_avicole.rename (columns={
                        "Disponibilité alimentaire" : "Aliments avicoles (Milliers de tonnes)"})

#résultat
df_aliment_avicole.head()
Out[136]:
Code zone Pays Aliments avicoles (Milliers de tonnes)
0 1 Arménie 138.0
1 2 Afghanistan 188.0
2 3 Albanie 398.0
3 4 Algérie 3973.0
4 7 Angola 789.0
In [138]:
pourcentage_nan = df_aliment_avicole.isna().sum()/len(df_aliment_avicole) *100
print(pourcentage_nan)
Code zone                                 0.0
Pays                                      0.0
Aliments avicoles (Milliers de tonnes)    0.0
dtype: float64


Vérification du nombre total d'habitants dans le monde , sachant qu'il devrait y avoir environ 7 milliards

In [143]:
population_mondiale_2017 = df_population[(df_population['Année']==2017)]
population_mondiale_2017.head(5)
Out[143]:
Code zone Pays Année Population
17 2 Afghanistan 2017 36296113.0
36 202 Afrique du Sud 2017 57009756.0
55 3 Albanie 2017 2884169.0
74 4 Algérie 2017 41389189.0
93 79 Allemagne 2017 82658409.0
In [145]:
print('Nombre de population en 2017 : ', population_mondiale_2017['Population'].sum()) 
Nombre de population en 2017 :  7548134111.0

Verification si doublons : non

In [148]:
def doublons(df): 
    print(len(df)-len(df.drop_duplicates()), 'doublons')

doublons(df_population) #changer la table pour verifier les autres
0 doublons

Mise au point Pays : nombre, pays manquants dans certaines df...

In [151]:
print('Nombre de pays :', df_population['Code zone'].nunique(), 'dans df_population')
print('Nombre de pays :', df_disponibiliteAlimentaire['Code zone'].nunique(), 'dans df_disponibiliteAlimentaire')
print('Nombre de pays :', df_stabilitePolitique['Code zone'].nunique(), 'dans df_stabilitePolitique')
print('Nombre de pays :', df_croissancePIB['Code zone'].nunique(), 'dans df_croissancePIB')
print('Nombre de pays :', df_rnb_par_hab['Code zone'].nunique(), 'dans df_rnb_par_hab')
print('Nombre de pays :', df_surfaceAgricole['Code zone'].nunique(), 'dans df_surfaceAgricole')
print('table dérivé:')
print('Nombre de pays :', df_croissancePopulation['Code zone'].nunique(), 'dans df_croissancePopulation')
print('Nombre de pays :', df_part_avicole['Code zone'].nunique(), 'dans df_part_avicole')
print('Nombre de pays :', df_tdi['Code zone'].nunique(), 'dans df_tdi')
print('Nombre de pays :', df_surfaceAgricole_complet['Code zone'].nunique(), 'dans df_surfaceAgricole_complet')
print('Nombre de pays :', df_aliment_avicole['Code zone'].nunique(), 'dans df_aliment_avicole')
Nombre de pays : 238 dans df_population
Nombre de pays : 174 dans df_disponibiliteAlimentaire
Nombre de pays : 195 dans df_stabilitePolitique
Nombre de pays : 210 dans df_croissancePIB
Nombre de pays : 210 dans df_rnb_par_hab
Nombre de pays : 227 dans df_surfaceAgricole
table dérivé:
Nombre de pays : 227 dans df_croissancePopulation
Nombre de pays : 172 dans df_part_avicole
Nombre de pays : 170 dans df_tdi
Nombre de pays : 227 dans df_surfaceAgricole_complet
Nombre de pays : 170 dans df_aliment_avicole
In [153]:
# Affichage Les pays dans dispAlim mais pas dans df_part_avicole

diff_countries = df_disponibiliteAlimentaire[~df_disponibiliteAlimentaire['Code zone'].isin(df_part_avicole['Code zone'])]

pays_manquants=diff_countries['Pays'].unique()
print('Les 2 pays manquants dans df_part_avicole sont :', pays_manquants)
Les 2 pays manquants dans df_part_avicole sont : ['Bermudes' 'Brunéi Darussalam']
In [155]:
# Affichage Les pays dans dispAlim mais pas dans df_tdi

diff_countries = df_disponibiliteAlimentaire[~df_disponibiliteAlimentaire['Code zone'].isin(df_tdi['Code zone'])]

pays_manquants=diff_countries['Pays'].unique()
print('Les 4 pays manquants dans df_tdi sont :', pays_manquants)
Les 4 pays manquants dans df_tdi sont : ['Bermudes' 'Brunéi Darussalam' 'Ouzbékistan'
 'République démocratique populaire lao']
In [157]:
# Affichage Les pays dans dispAlim mais pas dans df_aliment_avicole

diff_countries = df_disponibiliteAlimentaire[~df_disponibiliteAlimentaire['Code zone'].isin(df_aliment_avicole['Code zone'])]

pays_manquants=diff_countries['Pays'].unique()
print('Les 4 pays manquants dans df_aliment_avicole sont :', pays_manquants)
Les 4 pays manquants dans df_aliment_avicole sont : ['Bermudes' 'Brunéi Darussalam' 'Ouzbékistan'
 'République démocratique populaire lao']

La table disponibiliteAlimentaire contient le coeur des données fondamentales pour l'analyse.
Nous l'utiliserons pas directement mais nous utiliserons ses tables dérivées (df_tdi et df_part_avicole et df_aliment_avicole)

On remarque qu'il manque 2 pays dans df_part_avicole par rapport à la disponibilitéAlimentaire : Bermudes, Brunei Darussalam
et il manque 4 pays dans df_tdi : 'Bermudes','Brunéi Darussalam', 'Ouzbékistan', 'République démocratique populaire lao'

Nous pouvons donc supprimer systématiquement les pays : Bermudes, Brunei Darussalam
Puis nous choissisons de supprimer également les 2 autres pays qui n'impacte pas l'objectif initial (le choix de pays candidats prioritaires pour exportation).

Ainsi, nous allons prendre comme table de base en pivot la table df_tdi qui contient les pays ayant les données incontournables.

je vais donc vérifier la correspondance des pays entre df_tdi et les autres tables

In [160]:
#dans table population 
diff_countries = df_tdi['Code zone'].isin(df_population['Code zone']) == False
df_tdi[diff_countries].head(5) 
Out[160]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
In [162]:
#dans table df_stabilitePolitique
diff_countries = df_tdi['Code zone'].isin(df_stabilitePolitique['Code zone']) == False
df_tdi[diff_countries].head(20) 
Out[162]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
26 41 Chine, continentale 692.0 452.0 54694.0 0.83
45 70 Polynésie française 0.0 15.0 3.0 83.33
105 153 Nouvelle-Calédonie NaN 9.0 3.0 75.00
116 169 Paraguay 4.0 3.0 131.0 2.31
144 214 Chine, Taiwan Province de 11.0 163.0 1053.0 13.53

En fait dans stabilité politique, concernant la Chine, il n'y a que les valeurs de Macao (Code Zone 128) et Hong-Kong (Code Zone 96).
Cependant, nous avons les données (à partir du projet 8) de stabilité politique en 2017 de Taiwan (0.86) et de la Chine, continentale (-0.23).

De la même manière, nous trouvons aussi pour Paraguay en 2017 (0.0).

Pour les pays d'outre-mer français (Polynésie française, Nouvelle-Calédonie), nous retiendrons la valeur de la stabilité politique de la France, les bases ne proposant pas d'indicateur séparé. Bien que cela n'est pas fidèle à 100%
(ex : en Nouvelle-Calédonie, il y a eu plusieurs référendums sur l'independance, parfois des tensions.
ex2 : en Polynésie, la vie politique est plus stable, mais il existe des débats sur l'autonomie).

In [165]:
df_stabilitePolitique[df_stabilitePolitique["Pays"]=="France"]
Out[165]:
Code zone Pays Année Stabilité politique
63 68 France 2017 0.27
In [167]:
# Tableau des imputations à ajouter
imputations = pd.DataFrame([
    {"Code zone": 41, "Pays":"Chine, continentale","Stabilité politique":-0.23},
    {"Code zone": 70, "Pays":"Polynésie française","Stabilité politique":0.27},
    {"Code zone": 153, "Pays":"Nouvelle-Calédonie","Stabilité politique":0.27},
    {"Code zone": 169, "Pays":"Paraguay","Stabilité politique":0.0},
    {"Code zone": 214, "Pays":"Chine, Taiwan Province de","Stabilité politique":0.86}
     ])


#imputations des valeurs dans df_stabilitePolitique via concatenation
df_stabilitePolitique= pd.concat([df_stabilitePolitique, imputations], ignore_index=True)
In [169]:
df_stabilitePolitique[df_stabilitePolitique["Code zone"]==214] #changer le Code zone pour verifier les autres ajout 
Out[169]:
Code zone Pays Année Stabilité politique
199 214 Chine, Taiwan Province de NaN 0.86
In [171]:
#dans table df_stabilitePolitique
diff_countries = df_tdi['Code zone'].isin(df_stabilitePolitique['Code zone']) == False
df_tdi[diff_countries].head(20) 
Out[171]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
In [173]:
#dans table df_croissancePIB
diff_countries = df_tdi['Code zone'].isin(df_croissancePIB['Code zone']) == False
df_tdi[diff_countries].head(5) 
Out[173]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
144 214 Chine, Taiwan Province de 11.0 163.0 1053.0 13.53
In [175]:
#dans table df_rnb_par_hab
diff_countries = df_tdi['Code zone'].isin(df_rnb_par_hab['Code zone']) == False
df_tdi[diff_countries].head(5) 
Out[175]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
144 214 Chine, Taiwan Province de 11.0 163.0 1053.0 13.53

Les données macroéconomique (PIB,RNB...) ne sont pas disponibles dans FAOSTAT, en raison du statut politique particulier de Taiwan.
Pour obtenir le PIB nominal de Taiwan (sans correction de l'inflation comme dans mes données de FAO), nous utiliserons les données du DGBAS de Taiwan (équivalent de l'INSEE pour eux) : https://eng.stat.gov.tw//Point.aspx?sid=t.1&n=4200&sms=11713

On prendra
GDP(at Current Prices)(million NT dollars) = PIB nominal (non corrigé de l'inflation) de 2016 et 2017 pour calculer le taux de croissance :
((GDP 2017 - GDP 2016) / GDP 2016)100 = ((18 012 387 - 17 555 268)/17 555 268 )100= 2.60388506 %

Per Capita GNI(US dollars) = RNB/hab (US dollars) de 2017 = 25 745

In [178]:
df_croissancePIB[df_croissancePIB["Code zone"]==214]
Out[178]:
Code zone Pays Année taux de croissance du PIB (%)
In [180]:
df_rnb_par_hab[df_rnb_par_hab["Code zone"]==214]
Out[180]:
Code zone Pays Année RNB/hab (USD)
In [182]:
# Tableau des imputations à ajouter 
imputations_pib = pd.DataFrame([
    {"Code zone": 214, "Pays":"Chine, Taiwan Province de","taux de croissance du PIB (%)":2.603885}
     ])

imputations_rnb = pd.DataFrame([
    {"Code zone": 214, "Pays":"Chine, Taiwan Province de","RNB/hab (USD)":25745}
     ])

#imputations des valeurs via concatenation
df_croissancePIB= pd.concat([df_croissancePIB, imputations_pib], ignore_index=True)
df_rnb_par_hab= pd.concat([df_rnb_par_hab, imputations_rnb], ignore_index=True)
In [184]:
#dans table df_surfaceAgricole (c'est pareil pour df_surfaceAgricole_complet)
diff_countries = df_tdi['Code zone'].isin(df_surfaceAgricole['Code zone']) == False
df_tdi[diff_countries].head(5)
Out[184]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
88 128 Chine - RAS de Macao 0.0 36.0 3.0 92.31

L'agriculture à Macao n'existe quasiment pas.
Choix 1 : Nous pouvons imputer la valeur minimale trouvée dans notre table df_surfaceAgricole_complet : 0.000100 ha/hab.
Choix 2 : Nous pouvons supprimer Macao de notre table. Macao présente un tdi avicole de 92% mais cette valeur ne traduit pas une opportunité d'exportation. En pratique, Macao dépend quasi exclusivement des importations de la Chine continentale.

Nous retiendrons le second choix.

In [187]:
#supprimer Macao par son code Zone dans df_tdi 
df_tdi= df_tdi[df_tdi["Code zone"]!= 128]

#verification 
diff_countries = df_tdi['Code zone'].isin(df_surfaceAgricole['Code zone']) == False
df_tdi[diff_countries].head(5)
Out[187]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
In [189]:
#dans table df_croissancePopulation
diff_countries = df_tdi['Code zone'].isin(df_croissancePopulation['Code zone']) == False
df_tdi[diff_countries].head(5)
Out[189]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
167 272 Serbie 10.0 15.0 173.0 8.43
168 273 Monténégro 0.0 10.0 10.0 50.00
169 276 Soudan NaN 3.0 123.0 2.38

La Serbie, le Monténégro et le Soudan ne pourront pas être intégrés en raison de données manquantes sur la croissance démographique.
Leur profil n'étant pas stratégiquement pertinent (Faible dépendance aux importations ou marché trop petit), nous avons choisis de les exclure.

In [192]:
#supprimer les 3 pays par son code Zone dans df_tdi 
df_tdi= df_tdi[df_tdi["Code zone"]!= 272]
df_tdi= df_tdi[df_tdi["Code zone"]!= 273]
df_tdi= df_tdi[df_tdi["Code zone"]!= 276]

#verification 
diff_countries = df_tdi['Code zone'].isin(df_croissancePopulation['Code zone']) == False
df_tdi[diff_countries].head(5)
Out[192]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
In [194]:
#dans table df_aliment_avicole
diff_countries = df_tdi['Code zone'].isin(df_aliment_avicole['Code zone']) == False
df_tdi[diff_countries].head(5)
Out[194]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)
In [196]:
#dans table df_part_avicole
diff_countries = df_tdi['Code zone'].isin(df_part_avicole['Code zone']) == False
df_tdi[diff_countries].head(5)
Out[196]:
Code zone Pays Exportations - Quantité Importations - Quantité Production TDI_avicole (%)


Suppression colonnes inutiles (préparation des tables pour jointures)

In [201]:
#Suppression des colonnes inutiles df_tdi
df_tdi_jointure = df_tdi[["Code zone","Pays","Importations - Quantité","TDI_avicole (%)"]]
In [203]:
df_tdi_jointure
Out[203]:
Code zone Pays Importations - Quantité TDI_avicole (%)
0 1 Arménie 36.0 42.86
1 2 Afghanistan 83.0 63.36
2 3 Albanie 38.0 37.62
3 4 Algérie 2.0 0.30
4 7 Angola 300.0 86.46
... ... ... ... ...
162 244 Samoa 17.0 100.00
163 249 Yémen 78.0 25.00
164 251 Zambie 12.0 10.81
165 255 Belgique 458.0 141.36
166 256 Luxembourg 19.0 95.00

166 rows × 4 columns

In [205]:
#Suppression des colonnes inutiles df_croissancePIB
df_croissancePIB_jointure = df_croissancePIB[["Code zone","taux de croissance du PIB (%)"]]
In [207]:
df_croissancePIB_jointure.head()
Out[207]:
Code zone taux de croissance du PIB (%)
0 2 4.444345
1 202 17.791964
2 3 9.767331
3 4 6.287893
4 79 6.368624
In [209]:
#Suppression des colonnes inutiles df_rnb_par_hab
df_rnb_par_hab_jointure = df_rnb_par_hab[["Code zone","RNB/hab (USD)"]]
In [211]:
df_rnb_par_hab_jointure.head()
Out[211]:
Code zone RNB/hab (USD)
0 2 539.263388
1 202 6429.574062
2 3 4503.239709
3 4 4027.655361
4 79 45470.601480
In [213]:
#Suppression des colonnes inutiles  df_part_avicole
df_part_avicole_jointure = df_part_avicole[["Code zone","Quantité de produits avicoles (kg/hab/an) ","Part avicole (%)"]]
In [215]:
df_part_avicole_jointure.head()
Out[215]:
Code zone Quantité de produits avicoles (kg/hab/an) Part avicole (%)
23 38 12.05 90.60
74 109 53.08 87.10
68 103 24.39 85.58
58 91 40.20 85.39
132 194 49.92 82.27
In [217]:
#Suppression des colonnes inutiles df_croissancePopulation
df_croissancePopulation_jointure = df_croissancePopulation[["Code zone","CAGR (%/an), 2000-2018"]]
In [219]:
df_croissancePopulation_jointure.head()
Out[219]:
Code zone CAGR (%/an), 2000-2018
0 2 3.283677
1 202 1.403732
2 3 -0.454795
3 4 1.724390
4 79 0.116470
In [221]:
#Suppression des colonnes inutiles df_aliment_avicole
df_aliment_avicole_jointure = df_aliment_avicole[["Code zone","Aliments avicoles (Milliers de tonnes)"]]
In [223]:
df_aliment_avicole_jointure.head()
Out[223]:
Code zone Aliments avicoles (Milliers de tonnes)
0 1 138.0
1 2 188.0
2 3 398.0
3 4 3973.0
4 7 789.0
In [225]:
#Suppression des colonnes inutiles df_surfaceAgricole_complet
df_surfaceAgricole_complet_jointure = df_surfaceAgricole_complet[["Code zone","Pop_2017","Surface agricole par hab (ha/hab)"]]
In [227]:
df_surfaceAgricole_complet_jointure.head()
Out[227]:
Code zone Pop_2017 Surface agricole par hab (ha/hab)
0 2 36296113.0 1.0445
1 202 57009756.0 1.6899
2 3 2884169.0 0.4071
3 4 41389189.0 0.9987
4 79 82658409.0 0.2019
In [229]:
#Suppression des colonnes inutiles df_stabilitePolitique
df_stabilitePolitique_jointure = df_stabilitePolitique[["Code zone","Stabilité politique"]]
In [231]:
df_stabilitePolitique_jointure.head()
Out[231]:
Code zone Stabilité politique
0 2 -2.79
1 202 -0.28
2 3 0.37
3 4 -0.92
4 79 0.57
In [233]:
print("Base TDI :", df_tdi_jointure["Code zone"].nunique())

df_merge = df_tdi_jointure.merge(df_croissancePIB_jointure, on="Code zone", how="inner")
print("Après jointure avec taux de croissancePIB :", df_merge["Code zone"].nunique())

df_merge = df_merge.merge(df_rnb_par_hab_jointure, on="Code zone", how="inner")
print("Après jointure avec RNB/hab :", df_merge["Code zone"].nunique())

df_merge = df_merge.merge(df_part_avicole_jointure, on="Code zone", how="inner")
print("Après jointure avec part_avicole :", df_merge["Code zone"].nunique())

df_merge = df_merge.merge(df_croissancePopulation_jointure, on="Code zone", how="inner")
print("Après jointure avec croissancePopulation :", df_merge["Code zone"].nunique())

df_merge = df_merge.merge(df_aliment_avicole_jointure, on="Code zone", how="inner")
print("Après jointure avec aliment_avicole :", df_merge["Code zone"].nunique())

df_merge = df_merge.merge(df_surfaceAgricole_complet_jointure, on="Code zone", how="inner")
print("Après jointure avec surfaceAgricole_complet :", df_merge["Code zone"].nunique())

df_finale = df_merge.merge(df_stabilitePolitique_jointure, on="Code zone", how="inner")
print("Après jointure avec stabilitePolitique :", df_finale["Code zone"].nunique())
Base TDI : 166
Après jointure avec taux de croissancePIB : 166
Après jointure avec RNB/hab : 166
Après jointure avec part_avicole : 166
Après jointure avec croissancePopulation : 166
Après jointure avec aliment_avicole : 166
Après jointure avec surfaceAgricole_complet : 166
Après jointure avec stabilitePolitique : 166
In [235]:
df_finale.head()
Out[235]:
Code zone Pays Importations - Quantité TDI_avicole (%) taux de croissance du PIB (%) RNB/hab (USD) Quantité de produits avicoles (kg/hab/an) Part avicole (%) CAGR (%/an), 2000-2018 Aliments avicoles (Milliers de tonnes) Pop_2017 Surface agricole par hab (ha/hab) Stabilité politique
0 1 Arménie 36.0 42.86 9.305043 4094.332429 27.70 48.35 -0.217251 138.0 2944791.0 0.5692 -0.63
1 2 Afghanistan 83.0 63.36 4.444345 539.263388 3.03 30.03 3.283677 188.0 36296113.0 1.0445 -2.79
2 3 Albanie 38.0 37.62 9.767331 4503.239709 31.02 49.90 -0.454795 398.0 2884169.0 0.4071 0.37
3 4 Algérie 2.0 0.30 6.287893 4027.655361 14.81 55.93 1.724390 3973.0 41389189.0 0.9987 -0.92
4 7 Angola 300.0 86.46 20.766649 3788.156996 11.23 46.50 3.566730 789.0 29816766.0 1.5349 -0.39

j'ai oublié de supprimer la France, donc je le fais ici.

In [238]:
df_finale = df_finale[df_finale["Code zone"]!= 68]
print("Nombre de pays retenu :", df_finale["Code zone"].nunique())
Nombre de pays retenu : 165

Verification NaN

In [241]:
pourcentage_nan = df_finale.isna().sum()/len(df_finale) *100
print(pourcentage_nan)
Code zone                                     0.0
Pays                                          0.0
Importations - Quantité                       0.0
TDI_avicole (%)                               0.0
taux de croissance du PIB (%)                 0.0
RNB/hab (USD)                                 0.0
Quantité de produits avicoles (kg/hab/an)     0.0
Part avicole (%)                              0.0
CAGR (%/an), 2000-2018                        0.0
Aliments avicoles (Milliers de tonnes)        0.0
Pop_2017                                      0.0
Surface agricole par hab (ha/hab)             0.0
Stabilité politique                           0.0
dtype: float64

3) Analyse exploratoire des données : comprendre ce qu'on a en face de nous¶

a) Description des données "Photo d'ensemble" :

In [245]:
df_finale.info()
<class 'pandas.core.frame.DataFrame'>
Index: 165 entries, 0 to 165
Data columns (total 13 columns):
 #   Column                                      Non-Null Count  Dtype  
---  ------                                      --------------  -----  
 0   Code zone                                   165 non-null    int64  
 1   Pays                                        165 non-null    object 
 2   Importations - Quantité                     165 non-null    float64
 3   TDI_avicole (%)                             165 non-null    float64
 4   taux de croissance du PIB (%)               165 non-null    float64
 5   RNB/hab (USD)                               165 non-null    float64
 6   Quantité de produits avicoles (kg/hab/an)   165 non-null    float64
 7   Part avicole (%)                            165 non-null    float64
 8   CAGR (%/an), 2000-2018                      165 non-null    float64
 9   Aliments avicoles (Milliers de tonnes)      165 non-null    float64
 10  Pop_2017                                    165 non-null    float64
 11  Surface agricole par hab (ha/hab)           165 non-null    float64
 12  Stabilité politique                         165 non-null    float64
dtypes: float64(11), int64(1), object(1)
memory usage: 18.0+ KB

Note, première observation :
On a 165 pays
13 colonnes dont 11 indicateurs
Aucun NaN
Types corrects

In [248]:
df_finale.describe()
Out[248]:
Code zone Importations - Quantité TDI_avicole (%) taux de croissance du PIB (%) RNB/hab (USD) Quantité de produits avicoles (kg/hab/an) Part avicole (%) CAGR (%/an), 2000-2018 Aliments avicoles (Milliers de tonnes) Pop_2017 Surface agricole par hab (ha/hab) Stabilité politique
count 165.00000 165.000000 165.000000 165.000000 165.000000 165.000000 165.000000 165.000000 165.000000 1.650000e+02 165.000000 165.000000
mean 123.69697 104.587879 34.472242 7.720804 13469.461597 27.390545 48.587394 1.392066 5101.618182 4.372202e+07 1.312370 -0.069455
std 71.10422 223.348519 38.389104 6.294400 17761.607275 18.694425 19.208446 1.225384 22746.718042 1.561646e+08 3.612748 0.884375
min 1.00000 0.000000 0.000000 -23.927708 454.350854 0.560000 2.950000 -1.232440 0.000000 5.204500e+04 0.000700 -2.930000
25% 63.00000 4.000000 3.240000 5.209157 1906.725675 9.220000 34.030000 0.514754 50.000000 2.884169e+06 0.188700 -0.630000
50% 119.00000 19.000000 19.350000 7.449328 5774.905142 27.040000 49.330000 1.295638 552.000000 9.785843e+06 0.411900 0.000000
75% 184.00000 99.000000 61.540000 9.906242 17175.916365 39.120000 63.130000 2.302551 2716.000000 2.940248e+07 0.932600 0.640000
max 256.00000 1333.000000 248.610000 25.722423 81099.824689 77.380000 90.600000 6.435566 245001.000000 1.421022e+09 36.440300 1.560000

Note, première observation :
Les indicateurs présentent une forte variabilité entre pays. Ces disparités confirment la nécessité de norrmaliser les données et de traiter les outliers avant le clustering.

b) Distribution de chaque variable "comprendre la forme des données pour chaque indicateur" :

In [252]:
import matplotlib.pyplot as plt
import seaborn as sns 
In [253]:
cols_to_plot= df_finale.drop(columns=["Code zone","Pays"])
#cols_to_plot.head()
In [254]:
#Histogrammes de toutes les variables numériques 

cols_to_plot.hist(figsize=(15,12),bins=30) #bins est le nombre de barre, d'intervalle
plt.suptitle("Distribution des variables (histogrammes)",fontsize=16)
plt.show()
No description has been provided for this image

Variables très asymétriques : importations, TDI avicole, RNB/hab, aliments avicoles, population, surface agricole/hab.
Variables plus équilibrées : part avicole, stabilité politique, croissance démographique,croissance PIB, quantité produits avicoles.

-> envisager une normalisation et un traitement des outliers.

In [256]:
#Boxplots pour toutes les variables numériques 

#layout (affichage des figures sur 3 colonnes et 4 lignes)
cols=3
rows=4
plt.figure(figsize=(16,4*rows)) #taille des figures 

for i, col in enumerate(cols_to_plot.columns,start=1):
    ax=plt.subplot(rows,cols,i)
    sns.boxplot(x=cols_to_plot[col],orient='h',width=0.6,fliersize=3)
    ax.set_title(col,fontsize=10)
    ax.grid(axis='x',linestyle=':',linewidth=0.5)

plt.savefig("box_plot_indicateurs.png",dpi=300, bbox_inches="tight")
plt.tight_layout()
plt.show()
No description has been provided for this image
In [257]:
#Boxplots log(1+x) pour les variables très skewed

skewed_candidats= ['Importations - Quantité','RNB/hab (USD)','Pop_2017','Aliments avicoles (Milliers de tonnes)','Surface agricole par hab (ha/hab)','TDI_avicole (%)']
skewed_candidats= [c for c in skewed_candidats if c in df_finale.columns]

plt.figure(figsize=(14,3.5*len(skewed_candidats))) #taille des figures 

for i, col in enumerate(skewed_candidats,1):
    ax=plt.subplot(len(skewed_candidats),1,i)
    sns.boxplot(x=np.log1p(cols_to_plot[col]),orient='h', width=0.6, fliersize=3)
    ax.set_title(f"{col}- log1p-transformed",fontsize=11)
    ax.grid(axis='x',linestyle=':',linewidth=0.5)


plt.savefig("box_plot_normaliser_indicateurs.png",dpi=300, bbox_inches="tight")
plt.tight_layout()
plt.show()
    
No description has been provided for this image

Pour importations, RNB/ hab, aliments avicoles :
Après log(1+x), la compression de l'echelle a "absorbé" les extrêmes. PLus d'outliers visibles, distributions "propres".

Population : Même après log, il reste 4 outliers car ils sont vraiment hors norme démographiquement.
Ici, le log aide mais ne peut pas effacer le fait qu'ils soient hors normes comparés aux autres -> ce sont des "vraies outliers structurels".

Surface ag/hab : Encore beaucoup d'outliers après log. #vu en version sans inverse
Normal aussi : certains pays ont des surfaces agricoles immenses par rapport à leur population (ex: Australie, Canada, Kazakhstan..).
Ce n'est pas du "bruit" mais une réalité géographique.

In [259]:
#statistiques rapides sur les outliers (IQR rule)

def outlier_stats(series): 
    s = series.dropna() 
    q1= s.quantile(0.25)
    q3= s.quantile(0.75)
    iqr= q3 - q1
    low= q1 - 1.5 * iqr
    high = q3 + 1.5 * iqr
    n_out = s[(s<low)|(s>high)].shape[0] 
    pct_out = 100 * n_out / s.shape[0] if s.shape[0]>0 else 0 
    return n_out, round(pct_out,2), low, high

for col in cols_to_plot.columns:
    n_out, pct_out, low, high = outlier_stats(cols_to_plot[col])
    print(f"{col:45s} -> outliers : {n_out:3d} ({pct_out:5.2f}%) | bounds: [{low:.3g},{high:.3g}]")

#df.shape[0] => nb lignes donc nb pays 
#df.shape[1] => nb colonnes (pas utile ici) 
Importations - Quantité                       -> outliers :  18 (10.91%) | bounds: [-138,242]
TDI_avicole (%)                               -> outliers :   1 ( 0.61%) | bounds: [-84.2,149]
taux de croissance du PIB (%)                 -> outliers :  19 (11.52%) | bounds: [-1.84,17]
RNB/hab (USD)                                 -> outliers :  20 (12.12%) | bounds: [-2.1e+04,4.01e+04]
Quantité de produits avicoles (kg/hab/an)     -> outliers :   0 ( 0.00%) | bounds: [-35.6,84]
Part avicole (%)                              -> outliers :   0 ( 0.00%) | bounds: [-9.62,107]
CAGR (%/an), 2000-2018                        -> outliers :   1 ( 0.61%) | bounds: [-2.17,4.98]
Aliments avicoles (Milliers de tonnes)        -> outliers :  23 (13.94%) | bounds: [-3.95e+03,6.72e+03]
Pop_2017                                      -> outliers :  19 (11.52%) | bounds: [-3.69e+07,6.92e+07]
Surface agricole par hab (ha/hab)             -> outliers :  18 (10.91%) | bounds: [-0.927,2.05]
Stabilité politique                           -> outliers :   2 ( 1.21%) | bounds: [-2.54,2.54]
In [260]:
#Liste les pays outliers 

def get_outliers(df,col):
    s= df[col].dropna()
    q1= s.quantile(0.25)
    q3= s.quantile(0.75)
    iqr= q3 - q1
    low = q1 - 1.5 * iqr 
    high = q3 + 1.5 * iqr
    outliers = df[(df[col]<low)|(df[col]>high)][["Pays", col]].reset_index(drop=True)
    return outliers, (low,high)

#Pays outliers pour Importations : CHANGER SELON LA COLONNE ETUDIER
out_import, bounds_import = get_outliers(df_finale,"Importations - Quantité") 
print("Seuils pour Importations - Quantité :", bounds_import)
print(out_import.to_string(index=False))
Seuils pour Importations - Quantité : (-138.5, 241.5)
                                               Pays  Importations - Quantité
                                             Angola                    300.0
                                Chine, continentale                    452.0
                                               Cuba                    313.0
                                          Allemagne                   1333.0
                           Chine - RAS de Hong-Kong                   1074.0
                                               Iraq                    798.0
                                              Japon                   1105.0
                                            Mexique                   1040.0
                                           Pays-Bas                    880.0
                                        Philippines                    253.0
                               Fédération de Russie                    318.0
                                    Arabie saoudite                    732.0
                                     Afrique du Sud                    516.0
                                            Espagne                    246.0
                                Émirats arabes unis                    478.0
Royaume-Uni de Grande-Bretagne et d'Irlande du Nord                    880.0
                                           Viet Nam                    295.0
                                           Belgique                    458.0

Sens, Cohérence des outliers = pas d'erreur de saisie
=> à conserver mais une normalisation doit être effectuée avant clustering.

c) Corrélations entre variables "détecter si certains indicateurs racontent la même histoire"

In [265]:
#Matrice de corrélation 

plt.figure(figsize=(12,8))
sns.heatmap(cols_to_plot.corr(), annot=True, cmap="coolwarm", fmt=".2f",vmin= -1, vmax=1, center=0) 
plt.title("Matrice de corrélation entre variables", fontsize=14)
plt.savefig("matrice_corr_variable.png",dpi=300, bbox_inches="tight")
plt.show()
No description has been provided for this image

d) Scatterplots

In [273]:
#focus sur certaines relations

#TDI vs PIB/hab
sns.scatterplot(data=cols_to_plot,x="RNB/hab (USD)", y="TDI_avicole (%)")
plt.xscale("log") #souvent utile car RNB/hab est très étalé
plt.show()
No description has been provided for this image

4) Exportation df_finale¶

In [276]:
df_finale.to_csv("Bouzouita_Hayette_df_finale_p9.csv", index=False)

SUITE : Voir Notebook2

In [ ]: