Dans “Nettoie rapidement ton dataset”, tu as commencé à préparer ton dataset à partir d’un fichier CSV de la Banque Mondiale.
Prochaine étape : le rendre exploitable pour aggréger les données, tracer des graphiques, et entrainer des modèles de Machine Learning.
Bref, dépivote le avec Pandas 😎
Qu’est-ce qui ne va pas dans ce format ?
Reprenons notre dataframe.
df.head(10)
| | Country Name | Country Code | Indicator Name | Indicator Code | 1962 | 1967 | 1972 | 1977 | 1982 | 1987 | 1992 | 1997 | 2001 | 2002 | 2005 | 2007 | 2012 | 2014 | 2017 |
|---:|:----------------------------|:---------------|:------------------------------------------------------------|:-----------------|-------:|-------:|-------:|---------:|----------:|----------:|-------------:|-------------:|-------:|----------:|-------:|----------:|----------:|-------:|---------:|
| 1 | Africa Eastern and Southern | AFE | Annual freshwater withdrawals, total (billion cubic meters) | ER.H2O.FWTL.K3 | nan | nan | nan | nan | nan | nan | 39.2086 | 44.5868 | nan | 55.2737 | nan | 59.1535 | 89.1317 | nan | 96.664 |
| 2 | Afghanistan | AFG | Annual freshwater withdrawals, total (billion cubic meters) | ER.H2O.FWTL.K3 | nan | nan | nan | 13.2685 | 19.6898 | 26.1111 | 23.4603 | 20.8095 | nan | 20.282 | nan | 20.282 | 20.282 | nan | 20.282 |
| 3 | Africa Western and Central | AFW | Annual freshwater withdrawals, total (billion cubic meters) | ER.H2O.FWTL.K3 | nan | nan | nan | nan | nan | 13.8415 | 18.4275 | 22.9528 | nan | 27.3871 | nan | 29.0718 | 29.834 | nan | 30.234 |
| 4 | Angola | AGO | Annual freshwater withdrawals, total (billion cubic meters) | ER.H2O.FWTL.K3 | nan | nan | nan | nan | nan | 0.48 | 0.541692 | 0.603385 | nan | 0.66652 | nan | 0.7057 | 0.7057 | nan | 0.7057 |
| 5 | Albania | ALB | Annual freshwater withdrawals, total (billion cubic meters) | ER.H2O.FWTL.K3 | nan | nan | nan | nan | nan | nan | 1.18356 | 1.43046 | nan | 1.66312 | nan | 1.26804 | 1.19539 | nan | 1.188 |
| 7 | Arab World | ARB | Annual freshwater withdrawals, total (billion cubic meters) | ER.H2O.FWTL.K3 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | 212.028 |
| 8 | United Arab Emirates | ARE | Annual freshwater withdrawals, total (billion cubic meters) | ER.H2O.FWTL.K3 | nan | nan | nan | nan | 1.06107 | 1.46373 | 1.6146 | 2.04144 | nan | 2.24999 | nan | 2.77073 | 2.69755 | nan | 2.562 |
| 9 | Argentina | ARG | Annual freshwater withdrawals, total (billion cubic meters) | ER.H2O.FWTL.K3 | nan | nan | nan | 27.6516 | 27.9095 | 28.1674 | 28.4246 | 29.2943 | nan | 31.6979 | nan | 35.0259 | 37.69 | nan | 37.69 |
| 10 | Armenia | ARM | Annual freshwater withdrawals, total (billion cubic meters) | ER.H2O.FWTL.K3 | nan | nan | nan | nan | nan | nan | nan | 1.85 | nan | 1.732 | nan | 3.012 | 2.941 | nan | 2.865 |
| 12 | Antigua and Barbuda | ATG | Annual freshwater withdrawals, total (billion cubic meters) | ER.H2O.FWTL.K3 | nan | nan | nan | nan | nan | nan | 0.00215333 | 0.00328667 | nan | 0.00442 | nan | 0.0049 | 0.0044 | nan | 0.0044 |
Les variables mesurées sont réparties dans plusieurs colonnes. Et les noms de colonnes sont elles-mêmes des informations (des variables d’identification), au même titre que les Country Code
. Et çà, pandas, seaborn et scikit-learn n’aiment pas trop.
Quel format voulons-nous obtenir ?
Tu dois isoler les variables d’identification et les variables mesurées sur une même ligne. Le nom des colonnes sert juste à savoir ce que tu trouveras dans la colonne.
Nous voulons obtenir un dataframe qui ressemble à :
année | code pays | prélévement en eau |
---|---|---|
2007 | ARG | 35.0259 |
2012 | ARG | 37.69 |
2017 | ARG | 37.69 |
2007 | ARM | 3.012 |
2012 | ARM | 2.941 |
2017 | ARM | 2.865 |
Finalement, ce format ressemble plus à celui d’une base de données relationnelle qu’à un tableau croisée dynamique sous excel 😶🌫️
The Hard Way
Pour transformer notre dataframe, il y a 2 chemins. Tu peux coder la transformation à la main. Avec un algo du genre :
list_of_df_to_concat = []
for col in df.columns[4:]:
temp_df = df.loc[:,['Country Name',col]]
temp_df.loc[:,['year']] = col
temp_df.columns = ['Country Name','withdrawal','year']
list_of_df_to_concat.append(temp_df)
df_hard_way = pd.concat(list_of_df_to_concat)
df_hard_way = df_hard_way.reindex(columns=['Country Name','year','withdrawal'])
df_hard_way = df_hard_way.dropna()
Cet algorithme itère sur chaque variable mesurée (les années) du dataframe principal :
temp_df = df.loc[:,['Country Name',col]]
extrait la variable mesuréecol
et la variable d’identificationCountry Name
dans un sous-dataframe,temp_df.loc[:,['year']] = col
assigne la nom de la colonne à une nouvelle variable d’identificationyear
,temp_df.columns = ['Country Name','withdrawal','year']
renomme les colonnes. La colonneyear
est encore en dernière position,list_of_df_to_concat.append(temp_df)
ajoute ce sous-dataframe dans une liste,pd.concat(list_of_df_to_concat)
concatène tous les dataframes de la liste dans un nouveau dataframe,df_hard_way.reindex(columns=['Country Name','year','withdrawal'])
change l’ordre des colonnes,df_hard_way.dropna()
supprime les colonnes qui contiennent desNan
.
Le dataframe est désormais utilisable 🔥
| | Country Name | year | withdrawal|
|----:|:---------------|-----:|----------:|
| 30 | Barbados | 1962 | 0.03 |
| 30 | Barbados | 1967 | 0.0375 |
| 250 | Uruguay | 1967 | 0.822 |
| 30 | Barbados | 1972 | 0.045 |
| 58 | Denmark | 1972 | 0.914 |
| 60 | Algeria | 1972 | 2.2 |
| 75 | Finland | 1972 | 3.4 |
| 83 | Ghana | 1972 | 0.345467 |
| 89 | Greece | 1972 | 4.26272 |
| 101 | Hungary | 1972 | 3.37456 |
The Easy Pandas Way
La même transformation est gérée nativement par la librairie Pandas avec la fonction Melt.
df = pd.melt(df, id_vars=['Country Name'], value_vars=df.columns[4:], var_name='year', value_name='withdrawal').dropna()
Et voilà !
id_vars=['Country Name']
identifie la liste des variables d’identification,df.columns[4:])
extrait la liste des colonnes du dataframe après la 4eme, ce qui évite d’insérer manuellement la liste des variables mesurées,value_vars=df.columns[4:])
identie la liste des variables mesurées,var_name='year'
renomme la variable d’identification qui contient les années (les noms de colonnes),value_name='withdrawal'
renomme la variable mesurée (les contenus des colonnes),pd.melt()
exécute le “dépivotage” du dataframe,.dropna()
… droppe les Nan 😂
Le dataframe obtenu est exactement le même.
| | Country Name | year | withdrawal|
|----:|:---------------|-----:|----------:|
| 30 | Barbados | 1962 | 0.03 |
| 30 | Barbados | 1967 | 0.0375 |
| 250 | Uruguay | 1967 | 0.822 |
| 30 | Barbados | 1972 | 0.045 |
| 58 | Denmark | 1972 | 0.914 |
| 60 | Algeria | 1972 | 2.2 |
| 75 | Finland | 1972 | 3.4 |
| 83 | Ghana | 1972 | 0.345467 |
| 89 | Greece | 1972 | 4.26272 |
| 101 | Hungary | 1972 | 3.37456 |
Ce que tu peux faire avec ce “Melted Dataframe”
Des aggrégations
Tu veux connaître le prélèvement moyen d’eau douce par pays ?
df.groupby(['Country Name']).mean()
Je te laisse imagine le code avec le dataframe d’origine …
| Country Name | withdrawal |
|:-----------------------------|--------------:|
| Afghanistan | 20.4964 |
| Africa Eastern and Southern | 64.003 |
| Africa Western and Central | 24.5356 |
| Albania | 1.32143 |
| Algeria | 5.25218 |
| Angola | 0.629814 |
| Antigua and Barbuda | 0.00392667 |
...
| World | 3880.97 |
| Yemen, Rep. | 3.40277 |
| Zambia | 1.61513 |
| Zimbabwe | 3.03137 |
Des graphiques avec seaborn ♥️
df = df.loc[df['Country Name'].isin(['Spain','France','Lithuania','Poland']),:]
sns.set(rc={"figure.figsize":(20, 4)})
sns.lineplot(x="annee", y="withdrawal",hue="Country Name",
data=df).set_title('Annual Freshwater Withdrawal')
Aussi simplement que çà.