# Calculs & dataframes :
import numpy as np
import pandas as pd
# Data visualisations :
#import matplotlib.pyplot as plt
%matplotlib inline
#from matplotlib.colors import ListedColormap, LinearSegmentedColormap
#import seaborn as sns
import plotly.express as px
from plotly.subplots import make_subplots
import plotly.graph_objects as go
# SQL
import sqlite3
# Data visualisations :
import plotly.express as px
from plotly.subplots import make_subplots
import plotly.graph_objects as go
# Définition des constantes
year_inf = 2014 # minimum disponible pour la FAO : 2014 (les données antérieures sont obtenues par des méthodes différentes)
year_sup = 2018
besoins_kcal_j = 1700 # besoins journaliers moyen en kilocalories
besoins_prot_kg_j = 50/1000 # besoins journaliers moyens en kg de protéines
df.isnull().sum()
df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 903169 entries, 0 to 903168
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 code_pays 903169 non-null object
1 pays 903169 non-null object
2 population 903169 non-null int64
3 annee 903169 non-null int64
4 id_indic 903169 non-null object
5 indicateur 903169 non-null object
6 code_produit 903169 non-null object
7 produit 903169 non-null object
8 valeur 903169 non-null float64
9 unite 903169 non-null object
10 origine 903169 non-null object
dtypes: float64(1), int64(2), object(8)
memory usage: 82.7+ MB
for ind in df.indicateur.unique():
print(ind, df.loc[df.indicateur == ind, "valeur"].describe(), sep='\n',end='\n\n')
Production
count 54670.000000
mean 1007.057108
std 11798.533294
min 0.000000
25% 0.000000
50% 11.040000
75% 139.000000
max 768594.000000
Name: valeur, dtype: float64
Importations - Quantité
count 77253.000000
mean 90.061619
std 866.053088
min -1.000000
25% 0.000000
50% 1.000000
75% 17.000000
max 95538.000000
Name: valeur, dtype: float64
Variation de stock
count 66102.000000
mean 12.316436
std 400.994798
min -13134.000000
25% 0.000000
50% 0.000000
75% 0.000000
max 49300.000000
Name: valeur, dtype: float64
Exportations - Quantité
count 61307.000000
mean 119.846326
std 1271.020678
min 0.000000
25% 0.000000
50% 0.030000
75% 10.000000
max 83606.000000
Name: valeur, dtype: float64
Disponibilité intérieure
count 81047.000000
mean 664.568729
std 9379.056074
min -3726.000000
25% 0.000000
50% 5.130000
75% 71.000000
max 768594.000000
Name: valeur, dtype: float64
Traitement
count 25079.000000
mean 528.792296
std 7266.848767
min 0.000000
25% 0.000000
50% 0.000000
75% 19.000000
max 340609.000000
Name: valeur, dtype: float64
Résidus
count 71717.000000
mean -0.889008
std 160.893419
min -10036.000000
25% 0.000000
50% 0.000000
75% 0.000000
max 18077.000000
Name: valeur, dtype: float64
Nourriture
count 73674.000000
mean 349.811281
std 4723.882505
min 0.000000
25% 0.000000
50% 4.000000
75% 47.000000
max 451702.000000
Name: valeur, dtype: float64
Disponibilité alimentaire en quantité (kg/personne/an)
count 73574.000000
mean 7.974134
std 23.002508
min 0.000000
25% 0.020000
50% 0.620000
75% 4.570000
max 390.960000
Name: valeur, dtype: float64
Disponibilité alimentaire (Kcal/personne/jour)
count 72974.000000
mean 33.834955
std 106.394331
min 0.000000
25% 0.000000
50% 3.000000
75% 20.000000
max 1733.000000
Name: valeur, dtype: float64
Disponibilité de protéines en quantité (g/personne/jour)
count 73081.000000
mean 0.963470
std 3.271877
min 0.000000
25% 0.000000
50% 0.030000
75% 0.390000
max 48.940000
Name: valeur, dtype: float64
Disponibilité de matière grasse en quantité (g/personne/jour)
count 73077.000000
mean 1.039579
std 3.362542
min 0.000000
25% 0.000000
50% 0.030000
75% 0.360000
max 63.420000
Name: valeur, dtype: float64
Pertes
count 28080.000000
mean 102.041239
std 1340.082187
min 0.000000
25% 0.000000
50% 2.000000
75% 20.000000
max 84582.000000
Name: valeur, dtype: float64
Aliments pour animaux
count 19801.000000
mean 342.444965
std 3804.058960
min 0.000000
25% 0.000000
50% 1.000000
75% 30.000000
max 195703.000000
Name: valeur, dtype: float64
Semences
count 10305.000000
mean 80.620374
std 555.080447
min 0.000000
25% 0.000000
50% 3.000000
75% 19.000000
max 16976.000000
Name: valeur, dtype: float64
Autres utilisations (non alimentaire)
count 27426.000000
mean 160.273392
std 5095.212775
min -11.000000
25% 0.000000
50% 0.000000
75% 2.000000
max 392455.000000
Name: valeur, dtype: float64
Alimentation pour touristes
count 14002.000000
mean 1.228539
std 15.632883
min -3.000000
25% 0.000000
50% 0.000000
75% 0.000000
max 1127.000000
Name: valeur, dtype: float64
df.loc[(df.indicateur=="Importations - Quantité") & (df.valeur < 0),["pays","annee","indicateur","produit","valeur","unite"]]
df.drop(index=df.loc[(df.indicateur=="Importations - Quantité") & (df.valeur < 0)].index, inplace=True)
df.loc[(df.indicateur=="Autres utilisations (non alimentaire)") & (df.valeur < 0),["pays","annee","indicateur","produit","valeur","unite"]]
df.drop(index=df.loc[(df.indicateur=="Autres utilisations (non alimentaire)") & (df.valeur < 0)].index, inplace=True)
df.loc[(df.indicateur=="Alimentation pour touristes") & (df.valeur < 0),["pays","annee","indicateur","produit","valeur","unite"]]
df.drop(index=df.loc[(df.indicateur=="Alimentation pour touristes") & (df.valeur < 0)].index, inplace=True)
df_dispo_alim.drop(index=df_dispo_alim.loc[df_dispo_alim.ratio_proteines>1].index, inplace=True)
df_dispo_alim.describe()
data = df_dispo_alim[["produit","ratio_kcal_kg","ratio_proteines"]].groupby("produit").agg("mean")
data[["ratio_kcal_kg"]].sort_values(by="ratio_kcal_kg", ascending=False).iloc[:15]
data[["ratio_proteines"]].sort_values(by="ratio_proteines", ascending=False).iloc[:15]
La disponibilité intérieure mondiale en produits végétaux est de 1.36e+16 kcal.
La disponibilité intérieure mondiale en produits végétaux est de 312057.2 kT de protéines.
print("Si toute la production végétale de {} était destinée à l'alimentation humaine :".format(year_sup),
" - l'équivalent en calories permettrait de nourrir {} milliards de personnes soit {} % de la population de {}."\
.format(round(nb_hab_prod_veg_kcal_ys/1e9,2),
round(100*nb_hab_prod_veg_kcal_ys/pop_monde_ys,1), year_sup),
" - l'équivalent en protéines permettrait de nourrir {} milliards de personnes soit {} % de la population de {}."\
.format(round(nb_hab_prod_veg_prot_ys/1e9,2),
round(100*nb_hab_prod_veg_prot_ys/pop_monde_ys,1), year_sup),
sep='\n'
)
Si toute la production végétale de 2018 était destinée à l'alimentation humaine :
- l'équivalent en calories permettrait de nourrir 21.93 milliards de personnes soit 289.0 % de la population de 2018.
- l'équivalent en protéines permettrait de nourrir 17.1 milliards de personnes soit 225.3 % de la population de 2018.
print("Si toute la production végétale de {} vouée à l'alimentation (humaines et animales + pertes) était destinée à l'alimentation humaine :"\
.format(year_sup),
" - l'équivalent en calories permettrait de nourrir {} milliards de personnes soit {} % de la population de {}."\
.format(round(nb_hab_prod_alim_veg_kcal_ys/1e9,2),
round(100*nb_hab_prod_alim_veg_kcal_ys/pop_monde_ys,1), year_sup),
" - l'équivalent en protéines permettrait de nourrir {} milliards de personnes soit {} % de la population de {}."\
.format(round(nb_hab_prod_alim_veg_prot_ys/1e9,2),
round(100*nb_hab_prod_alim_veg_prot_ys/pop_monde_ys,1), year_sup),
sep='\n'
)
Si toute la production végétale de 2018 vouée à l'alimentation (humaines et animales + pertes) était destinée à l'alimentation humaine :
- l'équivalent en calories permettrait de nourrir 12.32 milliards de personnes soit 162.4 % de la population de 2018.
- l'équivalent en protéines permettrait de nourrir 11.0 milliards de personnes soit 144.9 % de la population de 2018.
# Récupération de la variable "nourriture"
df_dispo_alim_totale_ys = df_dispo_alim.loc[df_dispo_alim.annee == year_sup, ["pays","produit","dispo_alim_kcal", "dispo_prot_kg","annee"]]
# Nombre d'humains pouvant être nourris
nb_hab_dispo_alim_tot_kcal_ys = df_dispo_alim_totale_ys.dispo_alim_kcal.sum() / (besoins_kcal_j * 365)
nb_hab_dispo_alim_tot_prot_ys = df_dispo_alim_totale_ys.dispo_prot_kg.sum() / (besoins_prot_kg_j * 365)
print("Concernant la nourriture disponible à l'alimentation humaine en {} :".format(year_sup),
" - l'équivalent en calories permettrait de nourrir {} milliards de personnes soit {} % de la population de {}."\
.format(round(nb_hab_dispo_alim_tot_kcal_ys/1e9,2),
round(100*nb_hab_dispo_alim_tot_kcal_ys/pop_monde_ys,1), year_sup),
" - l'équivalent en protéines permettrait de nourrir {} milliards de personnes soit {} % de la population de {}."\
.format(round(nb_hab_dispo_alim_tot_prot_ys/1e9,2),
round(100*nb_hab_dispo_alim_tot_prot_ys/pop_monde_ys,1), year_sup),
sep='\n'
)
Concernant la nourriture disponible à l'alimentation humaine en 2018 :
- l'équivalent en calories permettrait de nourrir 12.75 milliards de personnes soit 168.0 % de la population de 2018.
- l'équivalent en protéines permettrait de nourrir 12.28 milliards de personnes soit 161.8 % de la population de 2018.
En 2018, au moins 7.17 % de la population mondiale souffrent de sous-alimentation soit 544.2 millions de personnes.
En 2017, au moins 7.06 % de la population mondiale souffrent de sous-alimentation soit 535.7 millions de personnes.
En 2016, au moins 6.97 % de la population mondiale souffrent de sous-alimentation soit 528.6 millions de personnes.
En 2015, au moins 6.91 % de la population mondiale souffrent de sous-alimentation soit 524.7 millions de personnes.
En 2014, au moins 6.9 % de la population mondiale souffrent de sous-alimentation soit 523.5 millions de personnes.
data = df_sousalim.loc[df_sousalim.annee == year_MA,:].copy()
data["nb_sous_alim"] = data["nb_sous_alim"].replace('<0.1',np.nan).astype("float64") * 1e6
fig = px.choropleth(data,
locations="code_pays",
color="nb_sous_alim",
hover_name="pays",
hover_data=["annee"],
color_continuous_scale="Reds",
labels={"nb_sous_alim":"Nombre"},
)
fig.layout.update(title="<b>Nombre de personnes sous-alimentées par pays en {}.<b>".format(year_MA),
#template=mon_theme,
geo_showframe=False,
height=600,
annotations = [dict(x=0.85, y=-0.05,
text='Source: <a href="http://www.fao.org/faostat/fr/#data/FBS"> FAO</a>',
showarrow = False
)]
)
fig.show()
df_cereales = df_cereales[["code_produit","produit"]].drop_duplicates(subset=["code_produit", "produit"])
df_cereales
À lui seul, en 2018, l'élevage a consommé 949.61 millions de tonnes de céréales soit 42.27 % des céréales destinées à l'alimentation (humaine et animale).
# Calcul de la quantité libérée par une baisse de 10% de l'élevage
print("Si en {} les États-Unis avaient réduit de {} % leur élevage, cela aurait libéré {} millions de tonnes de céréales."\
.format(year_sup, int(100*reduc_elevage),round(reduc_elevage*cereales_usa_ys.quantite_alim_anim_kT.sum()/1000,2)),
end='\n\n')
print("Cela équivaut aux besoins moyens de :",
" - {} millions de personnes (en nombre annuel de calories)"\
.format(round(reduc_elevage*df_cereales_usa_ys.cereales_anim_kcal.sum()/(besoins_kcal_j * 365)/1e6,2)),
" - {} millions de personnes (en quantité annuelle de protéines)"\
.format(round(reduc_elevage*df_cereales_usa_ys.cereales_anim_prot_kg.sum()/(besoins_prot_kg_j * 365)/1e6,2)),
sep='\n', end='\n\n'
)
print("Rappellons qu'en {}, au moins {} millions de personnes étaient sous-alimentées."\
.format(year_sup, round(df_sousalim.loc[df_sousalim.annee == year_MA,"nb_sous_alim"].replace('<0.1',np.nan).astype("float64").sum(),2)),
end='\n\n')
Si en 2018 les États-Unis avaient réduit de 10 % leur élevage, cela aurait libéré 14.21 millions de tonnes de céréales.
Cela équivaut aux besoins moyens de :
- 63.7 millions de personnes (en nombre annuel de calories)
- 41.11 millions de personnes (en quantité annuelle de protéines)
Rappellons qu'en 2018, au moins 523.5 millions de personnes étaient sous-alimentées.
# Extraction des données
year_MA = str(year_sup-1)+"-"+str(year_sup+1)
df_pays_sous_alim = df_sousalim.loc[df_sousalim.annee==year_MA,["pays","nb_sous_alim","unite","annee"]].dropna()
df_pays_sous_alim
# Tri par valeur décroissante ratio entre la quantité destinés aux "Autres utilisations" et la disponibilité intérieure
df_group_import.reset_index()\
.sort_values(by="ratio_autre_util_dispo_int", ascending=False)\
.loc[:,["produit","ratio_autre_util_dispo_int"]]\
.iloc[:5]\
.style.format({"ratio_autre_util_dispo_int":"{:.0%}"})
# Tri par valeur décroissante du ratio nourriture animale/nourriture totale
df_group_import.reset_index()\
.sort_values(by="ratio_alim_anim_nourriture", ascending=False)\
.loc[:,["produit","ratio_alim_anim_nourriture"]]\
.iloc[:5]\
.style.format({"ratio_alim_anim_nourriture":"{:.0%}"})
manioc_thailande_export = int(df_aniveg.loc[(df_aniveg.produit=="Manioc et produits") & (df_aniveg.annee==year_sup) & (df_aniveg.pays=="Thaïlande") & (df_aniveg.indicateur=="Exportations - Quantité"),"valeur"])
manioc_thailande_prod = int(df_aniveg.loc[(df_aniveg.produit=="Manioc et produits") & (df_aniveg.annee==year_sup) & (df_aniveg.pays=="Thaïlande") & (df_aniveg.indicateur=="Production"),"valeur"])
print("En {}, la Thaïlande a exporté {} millions de tonnes de manioc (équivalant {} % de sa production)\nalors que {} millions de personnes souffraient de sous-nutrition."\
.format(year_sup,
manioc_thailande_export/1000,
round(100*manioc_thailande_export/manioc_thailande_prod,1),
float(df_sousalim.loc[(df_sousalim.annee==year_MA) & (df_sousalim.pays=="Thaïlande"), "nb_sous_alim"])
))
En 2018, la Thaïlande a exporté 22.299 millions de tonnes de manioc (équivalant 75.9 % de sa production)
alors que 6.5 millions de personnes souffraient de sous-nutrition.
# Connexion à la BDD
cnx = sqlite3.connect("bdd_malnutrition.db", timeout=10)
# Création du curseur
cursor = cnx.cursor()
# Création de la Table
query_pop = """CREATE TABLE IF NOT EXISTS 'population'
('pays' INTEGER NOT NULL,
'code_pays' INTEGER NOT NULL UNIQUE,
'annee' INTEGER NOT NULL,
'population' INTEGER NOT NULL,
PRIMARY KEY('code_pays'))
;"""
cursor.execute(query_pop)
# Sélection des données
df_code_pays = pd.read_csv("https://raw.githubusercontent.com/vaubantis/malnutrition_fao/main/code_pays_FR.csv").rename(columns={"Zone":"pays","Code zone":"code_pays"})
table_pop = pd.merge(df_population, df_code_pays, on="code_pays", how="left").loc[:,["pays","code_pays","annee","population"]].dropna()
# Insertion des données
table_pop.to_sql(name='population', con=cnx, if_exists='replace', index=False)
pd.read_sql_query("""
SELECT produit, sum(alim_animale) , sum(nourriture) , round(100*sum(alim_animale)/(sum(alim_animale)+sum(nourriture)),1) AS ratio
FROM equilibre_prod ep
WHERE produit IN ("Blé et produits","Riz et produits","Orge et produits","Maïs et produits","Seigle et produits","Millet et produits","Avoine","Sorgho et produits","Céréales, Autres","Soja")
GROUP BY produit
ORDER BY ratio DESC
;""",
con = cnx)
pd.read_sql_query("""
SELECT pays, sum(nourriture) AS Quantité_T
FROM equilibre_prod ep
WHERE produit IN ("Blé et produits","Riz et produits","Orge et produits","Maïs et produits","Seigle et produits","Millet et produits","Avoine","Sorgho et produits","Céréales, Autres")
AND pays IN ("Allemagne","Autriche","Belgique","Bulgarie","Chypre","Croatie","Danemark","Espagne",
"Estonie","Finlande","France","Grèce","Hongrie","Irlande","Italie","Lettonie","Lituanie","Luxembourg","Malte","Pays-Bas","Pologne",
"Portugal","Tchéquie (la)","Roumanie","Slovaquie","Slovénie","Suède")
GROUP BY pays
ORDER BY sum(nourriture) DESC
LIMIT 15
;""",
con = cnx)
pd.read_sql_query("""
SELECT pays, sum(alim_animale) as Quantité_T
FROM equilibre_prod ep
WHERE produit IN ("Blé et produits","Riz et produits","Orge et produits","Maïs et produits","Seigle et produits","Millet et produits","Avoine","Sorgho et produits","Céréales, Autres")
AND pays IN ("Allemagne","Autriche","Belgique","Bulgarie","Chypre","Croatie","Danemark","Espagne",
"Estonie","Finlande","France","Grèce","Hongrie","Irlande","Italie","Lettonie","Lituanie","Luxembourg","Malte","Pays-Bas","Pologne",
"Portugal","Tchéquie (la)","Roumanie","Slovaquie","Slovénie","Suède")
GROUP BY pays
ORDER BY sum(alim_animale) DESC
LIMIT 15
;""",
con = cnx)
pd.read_sql_query("""
SELECT ep.code_pays, ep.pays, sum(pertes) as pertes_totale_tonnes, pop.population, ROUND(1e3*sum(pertes)/pop.population, 1) as "pertes_kg/hab"
FROM equilibre_prod as ep
INNER JOIN population as pop
ON pop.pays = ep.pays AND pop.annee = ep.annee
WHERE ep.annee = 2018
GROUP BY ep.pays
ORDER BY "pertes_kg/hab" DESC
;""",
con = cnx)
data = pd.read_sql_query("""
SELECT ep.code_pays, ep.pays, sum(pertes)/1e6 as pertes_totale_Mtonnes, pop.population, ROUND(1e3*sum(pertes)/pop.population, 1) as "pertes_kg/hab"
FROM equilibre_prod as ep
INNER JOIN population as pop
ON pop.pays = ep.pays AND pop.annee = ep.annee
GROUP BY ep.pays
ORDER BY "pertes_kg/hab" DESC
;""",
con = cnx)
fig = px.choropleth(data,
locations="code_pays",
color="pertes_kg/hab",
hover_name="pays",
hover_data=["pertes_kg/hab","pertes_totale_Mtonnes"],
color_continuous_scale="RdYlGn_r",
labels={"pertes_kg/hab":"Perte (kg/hab)","pertes_totale_Mtonnes":"Pertes totales (millions de tonnes)"},
)
fig.layout.update(title="<b>Gaspillage alimentaire par pays en {}.<b>".format(year_sup),
#template=mon_theme,
geo_showframe=False,
height=600,
annotations = [dict(
x=0.85,
y=0,
text='Source: <a href="http://www.fao.org/faostat/fr/#data/FBS"> FAO</a>',
showarrow = False
)]
)
fig.show()
data = pd.read_sql_query("""
SELECT ep.annee, ep.pays, sum(pertes) as pertes_totale_tonnes, pop.population, ROUND(1e3*sum(pertes)/pop.population, 1) as "pertes_kg/hab"
FROM equilibre_prod as ep
INNER JOIN population as pop
ON pop.pays = ep.pays AND pop.annee = ep.annee
WHERE ep.pays="France"
GROUP BY ep.annee
ORDER BY ep.annee DESC
LIMIT 15
;""",
con = cnx)
data
fig = px.line(data, x='annee', y='pertes_kg/hab', labels={"annee":"Année","pertes_kg/hab":"Pertes alimentaires (kg/hab)"})
fig.update_traces(line_color="skyblue")
fig.update_xaxes(dtick=1)
fig.update_yaxes(range=[0,121])
fig.layout.update(title="<b>Évolution du gaspillage alimentaire en France depuis {}<b>".format(year_inf),
template=mon_theme,
height=500
)
fig.show()
# Fermeture de la connexion à la BDD
cnx.close()