Depuis novembre 2021, j’accompagne les étudiants dans leur parcours de Data Scientist sur openclassrooms. Bref, je suis mentor. Je suis celui que j’aurai aimé rencontrer quand j’ai commencé à me former en ligne en 2016.
Je consacre mes vendredis après-midi à discuter avec eux, à les encourager, à répondre à leurs questions, à les rassurer parfois aussi. Et je t’avoue que je commence à m’attacher à ces personnes qui bossent intensément pour acquérir ces nouvelles compétences.
Je me suis aperçu qu’ils/elles se posent souvent les mêmes questions. Alors, voici une série d’articles Tech / Datascience pour documenter en français, les trucs que personne ne te dit quand tu démarres.
Bienvenue à bord !
Les Datasets de la Banque Mondiale
La WorldBank met à ta disposition, pas mal de Datasets très utiles pour te faire la main en datascience. Pour cet article, j’ai sélectionné le jeux de données sur les prélèvements annuels en eau douce dans le monde. Tu peux télécharger le jeux de données et les fichiers de métadata.
Aujourd’hui, nous allons nous concentrer sur le jeux de données. Avant de pouvoir en faire quelque chose, jettons un oeil dessus …
Charge ton jeux de données avec Pandas
J’utilise Pandas et Jupyter Lab
Le jeux de données est dans le fichier API_ER.H2O.FWTL.K3_DS2_en_csv_v2_3683647.csv
. Tu peux le charger dans ton notebook avec la librairie pandas.
import pandas as pd
df = pd.read_csv('./API_ER.H2O.FWTL.K3_DS2_en_csv_v2_3683647.csv')
Voilà à quoi il ressemble …
df.head()
| | Country Name | Country Code | Indicator Name | Indicator Code | 1960 | 1961 | 1962 | 1963 | 1964 | 1965 | 1966 | 1967 | 1968 | 1969 | 1970 | 1971 | 1972 | 1973 | 1974 | 1975 | 1976 | 1977 | 1978 | 1979 | 1980 | 1981 | 1982 | 1983 | 1984 | 1985 | 1986 | 1987 | 1988 | 1989 | 1990 | 1991 | 1992 | 1993 | 1994 | 1995 | 1996 | 1997 | 1998 | 1999 | 2000 | 2001 | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | Unnamed: 65 |
|---:|:----------------------------|:---------------|:------------------------------------------------------------|:-----------------|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|-------:|-----------:|-------:|-------:|-------:|-------:|-----------:|-------:|-------:|-------:|-------:|----------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|--------------:|
| 0 | Aruba | ABW | 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 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
| 1 | Africa Eastern and Southern | AFE | 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 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | 39.2086 | nan | nan | nan | nan | 44.5868 | nan | nan | nan | nan | 55.2737 | nan | nan | nan | nan | 59.1535 | nan | nan | nan | nan | 89.1317 | nan | nan | nan | nan | 96.664 | nan | nan | nan | nan |
| 2 | Afghanistan | AFG | 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 | nan | nan | nan | 13.2685 | nan | nan | nan | nan | 19.6898 | nan | nan | nan | nan | 26.1111 | nan | nan | nan | nan | 23.4603 | nan | nan | nan | nan | 20.8095 | nan | nan | nan | nan | 20.282 | nan | nan | nan | nan | 20.282 | nan | nan | nan | nan | 20.282 | nan | nan | nan | nan | 20.282 | nan | nan | nan | nan |
| 3 | Africa Western and Central | AFW | 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 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | 13.8415 | nan | nan | nan | nan | 18.4275 | nan | nan | nan | nan | 22.9528 | nan | nan | nan | nan | 27.3871 | nan | nan | nan | nan | 29.0718 | nan | nan | nan | nan | 29.834 | nan | nan | nan | nan | 30.234 | nan | nan | nan | nan |
| 4 | Angola | AGO | 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 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | 0.48 | nan | nan | nan | nan | 0.541692 | nan | nan | nan | nan | 0.603385 | nan | nan | nan | nan | 0.66652 | nan | nan | nan | nan | 0.7057 | nan | nan | nan | nan | 0.7057 | nan | nan | nan | nan | 0.7057 | nan | nan | nan | nan |
Beaucoup de données manquantes (les “nan”), et la dernière colonne est semble abérrante.
Fais une rapide exploration de ton jeux de données
D’abord les dimensions de ton dataframe.
df.shape
(266, 66)
266 lignes, 66 colonnes. Et à priori, plusieurs colonnes sont potentiellement vides. Vérifions.
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 266 entries, 0 to 265
Data columns (total 66 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Country Name 266 non-null object
1 Country Code 266 non-null object
2 Indicator Name 266 non-null object
3 Indicator Code 266 non-null object
4 1960 0 non-null float64
5 1961 0 non-null float64
6 1962 1 non-null float64
7 1963 0 non-null float64
8 1964 0 non-null float64
9 1965 0 non-null float64
10 1966 0 non-null float64
11 1967 2 non-null float64
12 1968 0 non-null float64
13 1969 0 non-null float64
14 1970 0 non-null float64
15 1971 0 non-null float64
16 1972 16 non-null float64
17 1973 0 non-null float64
18 1974 0 non-null float64
19 1975 0 non-null float64
20 1976 0 non-null float64
21 1977 35 non-null float64
22 1978 0 non-null float64
23 1979 0 non-null float64
24 1980 0 non-null float64
25 1981 0 non-null float64
26 1982 55 non-null float64
27 1983 0 non-null float64
28 1984 0 non-null float64
29 1985 0 non-null float64
30 1986 0 non-null float64
31 1987 90 non-null float64
32 1988 0 non-null float64
33 1989 0 non-null float64
34 1990 0 non-null float64
35 1991 0 non-null float64
36 1992 124 non-null float64
37 1993 0 non-null float64
38 1994 0 non-null float64
39 1995 0 non-null float64
40 1996 0 non-null float64
41 1997 148 non-null float64
42 1998 0 non-null float64
43 1999 0 non-null float64
44 2000 0 non-null float64
45 2001 1 non-null float64
46 2002 164 non-null float64
47 2003 0 non-null float64
48 2004 0 non-null float64
49 2005 2 non-null float64
50 2006 0 non-null float64
51 2007 173 non-null float64
52 2008 0 non-null float64
53 2009 0 non-null float64
54 2010 0 non-null float64
55 2011 0 non-null float64
56 2012 181 non-null float64
57 2013 0 non-null float64
58 2014 1 non-null float64
59 2015 0 non-null float64
60 2016 0 non-null float64
61 2017 226 non-null float64
62 2018 0 non-null float64
63 2019 0 non-null float64
64 2020 0 non-null float64
65 Unnamed: 65 0 non-null float64
dtypes: float64(62), object(4)
memory usage: 137.3+ KB
Retirons les colonnes avec 0 non-null
. Elles ne contiennent aucune données.
De la même manière, certaines lignes semblent complètement vides. Retirons les aussi.
| | Country Name | Country Code | Indicator Name | Indicator Code | 1960 | 1961 | 1962 | 1963 | 1964 | 1965 | 1966 | 1967 | 1968 | 1969 | 1970 | 1971 | 1972 | 1973 | 1974 | 1975 | 1976 | 1977 | 1978 | 1979 | 1980 | 1981 | 1982 | 1983 | 1984 | 1985 | 1986 | 1987 | 1988 | 1989 | 1990 | 1991 | 1992 | 1993 | 1994 | 1995 | 1996 | 1997 | 1998 | 1999 | 2000 | 2001 | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | Unnamed: 65 |
|---:|:----------------------------|:---------------|:------------------------------------------------------------|:-----------------|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|-------:|-----------:|-------:|-------:|-------:|-------:|-----------:|-------:|-------:|-------:|-------:|----------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|-------:|---------:|-------:|-------:|-------:|--------------:|
| 0 | Aruba | ABW | 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 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
Élimine les colonnes qui ne contiennent pas de données
Cherchons les colonnes qui ont autant de cellules vides qu’il y a de lignes dans le dataframe.
nb_datas_rows, _ = df.shape
nb_datas_rows
contient le nombre de ligne du dataframe.
Affichons un extrait des colonnes entièrement vides du dataframe :
df.loc[:,df.isnull().sum() == nb_datas_rows].head()
df.isnull().sum()
additionne le nombre de cellules vides dans chaque colonne.
df.isnull().sum() == nb_datas_rows
génère une liste de booléens, de même dimension que le nombre de colonnes, valant True
si toutes les cellules de la colonne sont vides.
df.loc[:,<condition>]
extrait pour toutes les lignes du dataframe, les colonnes qui répondent à la condition.
Tu obtiens cet extrait avec les colonnes à supprimer :
| | 1960 | 1961 | 1963 | 1964 | 1965 | 1966 | 1968 | 1969 | 1970 | 1971 | 1973 | 1974 | 1975 | 1976 | 1978 | 1979 | 1980 | 1981 | 1983 | 1984 | 1985 | 1986 | 1988 | 1989 | 1990 | 1991 | 1993 | 1994 | 1995 | 1996 | 1998 | 1999 | 2000 | 2003 | 2004 | 2006 | 2008 | 2009 | 2010 | 2011 | 2013 | 2015 | 2016 | 2018 | 2019 | 2020 | Unnamed: 65 |
|---:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|--------------:|
| 0 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
| 1 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
| 2 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
| 3 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
| 4 | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan | nan |
De la même manière, tu peux visualiser les colonnes qui seront conservées.
df.loc[:,df.isnull().sum() < nb_datas_rows].head()
| | Country Name | Country Code | Indicator Name | Indicator Code | 1962 | 1967 | 1972 | 1977 | 1982 | 1987 | 1992 | 1997 | 2001 | 2002 | 2005 | 2007 | 2012 | 2014 | 2017 |
|---:|:----------------------------|:---------------|:------------------------------------------------------------|:-----------------|-------:|-------:|-------:|---------:|---------:|---------:|-----------:|-----------:|-------:|----------:|-------:|---------:|---------:|-------:|---------:|
| 0 | Aruba | ABW | 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 | nan |
| 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 |
Il ne te reste qu’à le sauvegarder. Attention à retirer le .head()
:)
df = df.loc[:,df.isnull().sum() < nb_datas_rows]
Élimine les lignes qui ne contiennent pas de données interessantes
df.shape
(266, 19)
Le dataframe contient que colonnes qui ne sont pas entièrement vides. Nous allons supprimer toutes les lignes qui ne contiennent aucune donnée. Tu as remarqué que les 4 premières colonnes sont systématiquement valorisées. Nous les excluons de notre comptage.
_, nb_datas_cols = df.iloc[:,4:].shape
nb_datas_cols
contient le nombre de colonnes du dataframe relatives aux années. C’est-à-dire sans compter les colonnes Country Name
, Country Code
, Indicator Name
ni Indicator Code
.
Affichons un extrait des lignes entièrement vides:
df.loc[df.isnull().sum(axis=1) == nb_datas_cols,:].head()
df.isnull().sum(axis=1)
additionne le nombre de cellules vides dans chaque ligne.
df.isnull().sum(axis=1) == nb_datas_cols
génère une liste de booléens, de même dimension que le nombre de lignes, valant True
si toutes les cellules de la ligne sont vides.
df.loc[<condition>,:]
extrait pour toutes les colonnes du dataframe, les lignes qui répondent à la condition.
Tu obtiens cet extrait de dataframe avec les lignes à supprimer :
| | Country Name | Country Code | Indicator Name | Indicator Code | 1962 | 1967 | 1972 | 1977 | 1982 | 1987 | 1992 | 1997 | 2001 | 2002 | 2005 | 2007 | 2012 | 2014 | 2017 |
|---:|:---------------|:---------------|:------------------------------------------------------------|:-----------------|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|-------:|
| 0 | Aruba | ABW | 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 | nan |
| 6 | Andorra | AND | 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 | nan |
| 11 | American Samoa | ASM | 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 | nan |
| 23 | Bahamas, The | BHS | 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 | nan |
| 27 | Bermuda | BMU | 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 | nan |
De la même manière, tu peux visualiser les lignes qui seront conservées.
df.loc[df.isnull().sum(axis=1) < nb_datas_rows,:].head()
| | 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 |
Il ne te reste qu’à le sauvegarder.
df = df.loc[df.isnull().sum(axis=1) < nb_datas_cols,:]
df.shape
(228, 19)
Conclusion
Tu as appris à charger un fichier CSV dans un dataframe pandas, à retirer rapidement les lignes et les colonnes inutiles. Tu remarques aussi que le dataframe ressemble encore beaucoup à un fichier excel avec les pays en ligne et les années en colonne. Ce format n’est pas adapté pour tracer des graphiques ou entrainer des modèles de Machine Learning.
Dans le prochain article, nous verrons comment remettre le dataframe en forme en une ligne de code : Remets ton fichier CSV dans le bon sens