Les tableaux de données : éléments de correction

On reprend le sujet en indiquant des éléments de correction sous cette forme :

élément de correction...

Un data frame est un tableau de données. En général, les données à analyser sont contenues dans un tel tableau de données. Leur manipulation est un pré-equis avant toute analyse, représentation ou exploitation des données. Ce TP propose une introduction aux éléments essentiels des tableaux de données en python, via le paquetage pandas.
La documentation sur pandas est disponible en ligne.

Introduction

Les tableaux de données sont disponibles dans le paquetage pandas. Il faut donc l'importer pour réaliser les manipulations. Il est courant de le surnommer pd en le chargeant par la commande import pandas as pd.
Un tableau de données est donc constitué d'un ensemble de lignes et de colonnes. Chaque ligne correspond à une donnée, chaque colonne correspond à un attribut. À l'intersection d'une ligne avec une colonne, on trouve la valeur de l'attribut pour la donnée. Si celle-ci est inconnue, on utilise généralement la valeur NA qui signifie Non Available, quoique cette convention ne soit pas toujours bien respectée.

Manipulations

Chargement du contenu d'un tableau de données

Les données d'un tableau sont généralement stockées dans un fichier. En préalable à toute analyse, les données doivent être chargées dans un data frame. Il existe de multiples formats pour stocker les données d'un tableau dans un fichier. L'un des plus répandus quand il s'agît de données simples est un fichier csv.
Comme dans un tableau de données, dans un fichier csv, chaque ligne correspond à une donnée et chaque colonne à un attribut. Sur une ligne, les valeurs des attributs sont séparées par une virgule. La première ligne du fichier csv peut indiquer le nom des attributs ; elle est optionnelle.
Dans ce TP, nous allons utiliser un jeu de données qui représentent la composition en différentes molécules d'olives. La fonction pandas qui charge un fichier csv est read_csv. Le fichier se trouve à cette url : https://philippe-preux.github.io/ensg/miashs/datasets/olives.csv.

À faire : dans python, en s'aidant si nécessaire de la documentation, charger ce fichier dans un objet dénommé olives.

Remarque pratique importante : il faut garder à l'esprit qu'un fichier csv peut être édité avec un éditeur de textes. Il n'est pas rare que l'on doive le modifier avant de pouvoir le charger dans Python ou d'en simplifier le traitement dans Python ; il n'est pas rare non plus que ces modifications soient plus faciles à réaliser dans un éditeur de textes que dans Python.

olives = pd.read_csv ("/home/ppreux/philippe-preux.github.io/ensg/miashs/datasets/olives.csv", header = 0)
    

Premiers pas

Une fois un jeu de données chargé, les toutes premières choses à faire consistent à simplement inspecter son contenu :

À faire :

Accès aux éléments d'un tableau de données

Pour analyser un jeu de données, il faut accéder aux valeurs des attributs des données. En particulier, il faut accéder à la valeur des attributs qui nous intéresse, pour les données qui nous intéressent.

Pour cela, on utilise les attributs loc [] et iloc []. iloc [] permet de sélectionner des lignes ou des colonnes par leurs indices. loc() est beaucoup plus général et permet de sélectionner des lignes ou des colonnes en indiquant un nom ou en les sélectionnant selon un critère.

À faire :

Quelques opérations simples

À faire : en consultant la documentation de pandas, effectuer les opérations suivantes :

>>> olives.iloc [:,5].mean()
228.8653846153846
>>> olives.iloc [:,5].mean ()
228.8653846153846
>>> olives.iloc [:,5].min ()
152
>>> olives.iloc [:,5].max ()
375
>>> olives.iloc [:,5].median ()
223.0
>>> olives.iloc [:,5].std ()
36.74493506956942
>>> olives.iloc [:,5].var ()
1350.190253266873
    

Mêmes choses pour les attributs 3 à 6.

>>> olives.iloc [:,3:7].var ()
palmitic        28423.351500
palmitoleic      2755.658322
stearic          1350.190253
oleic          164681.936512
dtype: float64
>>> olives.iloc [:,3:7].mean ()
palmitic       1231.741259
palmitoleic     126.094406
stearic         228.865385
oleic          7311.748252
dtype: float64
>>> olives.iloc [:,3:7].min ()
palmitic        610
palmitoleic      15
stearic         152
oleic          6300
dtype: int64
>>> olives.iloc [:,3:7].max ()
palmitic       1753
palmitoleic     280
stearic         375
oleic          8410
dtype: int64
>>> olives.iloc [:,3:7].median ()
palmitic       1201.0
palmitoleic     110.0
stearic         223.0
oleic          7302.5
dtype: float64
>>> olives.iloc [:,3:7].std ()
palmitic       168.592264
palmitoleic     52.494365
stearic         36.744935
oleic          405.810222
dtype: float64
>>> olives.iloc [:,3:7].var ()
palmitic        28423.351500
palmitoleic      2755.658322
stearic          1350.190253
oleic          164681.936512
dtype: float64
      

La méthode describe() donne plusieurs statistiques d'un coup. Testez-la et regardez la documentation pour comprendre ce qu'elle affiche.

Accès aux éléments d'un tableau de données, la suite

À faire :

>>> olives [olives.stearic == olives.stearic.min ()]
      Region Name  region  area  ...  linolenic  arachidic  eicosenoic
304  South-Apulia       1     3  ...         27         50          20

[1 rows x 11 columns]
>>> olives [olives.stearic == olives.stearic.max ()]
    Region Name  region  area  ...  linolenic  arachidic  eicosenoic
262      Sicily       1     4  ...         52         69          45

[1 rows x 11 columns]
    

ou

>>> olives.iloc [olives.stearic.argmin(),:]
Unnamed: 0     South-Apulia
region                    1
area                      3
palmitic               1420
palmitoleic             175
stearic                 152
oleic                  7004
linoleic               1149
linolenic                27
arachidic                50
eicosenoic               20
Name: 304, dtype: object
    

en utilisant la méthode argmin () qui donne l'indice de la valeur minimale.
Il existe aussi argmax ().

Pour les attributs numériques, on peut utiliser les méthodes de la bibliotèque numpy. Par exemple, pour calculer la valeur moyenne de l'attribut 5, on peut aussi écrire : np.mean (olives.iloc [:,5]) (en supposant que vous avez importé numpy en le renommant np).

À faire : répondre aux deux questions précédentes en utilisant des méthodes de la bibliothèque numpy.

>>> olives.iloc [np.argmin (olives.stearic)]
Region Name    South-Apulia
region                    1
area                      3
palmitic               1420
palmitoleic             175
stearic                 152
oleic                  7004
linoleic               1149
linolenic                27
arachidic                50
eicosenoic               20
Name: 304, dtype: object
>>> olives.iloc [np.argmax (olives.stearic)]
Region Name    Sicily
region              1
area                4
palmitic         1112
palmitoleic        68
stearic           375
oleic            7770
linoleic          448
linolenic          52
arachidic          69
eicosenoic         45
Name: 262, dtype: object
    

Attributs catégoriques

Un attribut catégorique, ou nominal, est un attribut dont la valeur est prise parmi un ensemble fixé de valeurs possibles. Par exemple une couleur parmi jaune, vert, rouge, orange, violet. Ainsi, l'attribut 0 est un attribut catégorique qui indique la région de provenance de l'olive. De même, malgré les apparences qui peuvent faire croire que les attributs 1 et 2 sont numériques, ce sont en fait des attributs catégoriques : l'attribut 2 est simplement un numéro correspondant à la valeur de l'attribut 0. Quant à l'attribut 1, c'est une valeur 1, 2 ou 3 qui indique grossiérement la zone géographique : sud de l'Italie (1), Sardaigne (2), nord de l'Italie (3).
Pour éviter des erreurs malencontreuse comme calculer la valeur moyenne d'un attribut catégorique, il faut indiquer explicitement les attributs catégoriques. Pour cela, on fait : olives ["Region Name"] = olives ["Region Name"].astype("category").
Vérifier maintenant que vous ne pouvez plus calculer la moyenne de cet attribut.

À faire :


On vérifie que python nous laisse calculer la moyenne des attributs region et area :
>>> olives.region.mean()
1.6993006993006994
>>> olives.area.mean()
4.59965034965035
    

On indique que ce sont des attributs nominaux :
>>> olives.region = olives.region.astype("category")
>>> olives.area = olives.area.astype("category")
    

et on ne peut plus calculer leur moyenne :
>>> olives.region.mean()
Traceback (most recent call last):
  [...]
TypeError: 'Categorical' with dtype category does not support reduction 'mean'
>>> olives.area.mean()
Traceback (most recent call last):
  [...]
TypeError: 'Categorical' with dtype category does not support reduction 'mean'
    
Toutes ces lignes incompréhensibles nous indique que python ne peut pas calculer la moyenne d'un attribut catégoriques.

Pour les attributs catégoriques, il est intéressant d'obtenir la liste des valeurs présentes dans le jeu de données et également le nombre de données dans chaque catégorie.

À faire :

>>> olives ["Region Name"].unique()
['North-Apulia', 'Calabria', 'South-Apulia', 'Sicily', 'Inland-Sardinia', 'Coast-Sardinia', 'Umbria', 'East-Liguria', 'West-Liguria']
Categories (9, object): ['Calabria', 'Coast-Sardinia', 'East-Liguria', 'Inland-Sardinia', ...,
                         'Sicily', 'South-Apulia', 'Umbria', 'West-Liguria']
>>> olives ["Region Name"].value_counts()
South-Apulia       206
Inland-Sardinia     65
Calabria            56
Umbria              51
East-Liguria        50
West-Liguria        50
Sicily              36
Coast-Sardinia      33
North-Apulia        25
Name: Region Name, dtype: int64