On reprend le sujet en indiquant des éléments de correction sous cette forme :
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.
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.
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)
Une fois un jeu de données chargé, les toutes premières choses à faire consistent à simplement inspecter son contenu :
À faire :
>>> olives.head (n=5) Unnamed: 0 region area ... linolenic arachidic eicosenoic 0 North-Apulia 1 1 ... 36 60 29 1 North-Apulia 1 1 ... 31 61 29 2 North-Apulia 1 1 ... 31 63 29 3 North-Apulia 1 1 ... 50 78 35 4 North-Apulia 1 1 ... 50 80 46 [5 rows x 11 columns]Si ce n'est pas ce que vous obtenez, la lecture n'a pas été effectuée correctement et la raison en est que vous avez mal utilisé la fonction pandas.
columns = {"Unnamed: 0": "Region Name"}
indique avec un dictionnaire la (ou les) colonne(s) à renommer.
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 :
olives.iloc [20:29,5]
olives.iloc [20:29,3:7]
À 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.
À 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
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 :
>>> olives.region.mean() 1.6993006993006994 >>> olives.area.mean() 4.59965034965035
>>> olives.region = olives.region.astype("category") >>> olives.area = olives.area.astype("category")
>>> 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
.>>> 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