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éecode paysprélévement en eau
2007ARG35.0259
2012ARG37.69
2017ARG37.69
2007ARM3.012
2012ARM2.941
2017ARM2.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ée col et la variable d’identification Country Name dans un sous-dataframe,
  • temp_df.loc[:,['year']] = col assigne la nom de la colonne à une nouvelle variable d’identification year,
  • temp_df.columns = ['Country Name','withdrawal','year'] renomme les colonnes. La colonne year 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 des Nan.

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')

Spain, France, Lithuania & Poland Annual Freshwater Withdrawal

Aussi simplement que çà.

Références