Tableaux de données

Avant de commencer, chargez les modules nécessaires :

In [1]:
import pandas as pd
import numpy as np

Dans le module pandas, l'objet dataframe est un tableau de données.

Un dataframe contient des colonnes, qui ont toutes la même longueur, mais qui ne sont pas nécessairement toutes du même type (à l'opposé de np.array, où tous les éléments doivent être du même type).

En statistique, les colonnes correspondent aux variables observées et les lignes aux données observées sur un individu.

Les colonnes peuvent porter des noms (aussi appelés labels).

Par défaut, les lignes sont indexées par des entiers ($0,1,\dots$), mais l'utilisateur peut définir les indices comme bon lui semble.

Voici un exemple pour définir un premier dataframe.

In [2]:
mon_premier_df = pd.DataFrame(np.random.rand(6,4))
mon_premier_df
Out[2]:
0 1 2 3
0 0.330111 0.551144 0.477853 0.706378
1 0.794460 0.097998 0.683085 0.959816
2 0.521702 0.562092 0.029139 0.331993
3 0.582018 0.582167 0.250028 0.196901
4 0.003690 0.851699 0.051846 0.610007
5 0.424104 0.106381 0.859439 0.060212

Maintenant ajoutons les noms de variables :

In [3]:
mon_premier_df = pd.DataFrame(np.random.rand(6,4), columns=list('ABCD'))
mon_premier_df
Out[3]:
A B C D
0 0.843602 0.589955 0.926301 0.272442
1 0.150702 0.560934 0.398884 0.256153
2 0.297164 0.857896 0.723788 0.556637
3 0.722625 0.861942 0.877504 0.336861
4 0.440113 0.348621 0.485215 0.713990
5 0.380142 0.357138 0.087946 0.058523

Indexer les lignes différement. Exemple: utiliser des dates comme indice :

In [4]:
dates = pd.date_range('20160126', '20160131')
dates
Out[4]:
DatetimeIndex(['2016-01-26', '2016-01-27', '2016-01-28', '2016-01-29',
               '2016-01-30', '2016-01-31'],
              dtype='datetime64[ns]', freq='D')
In [5]:
df = pd.DataFrame(np.random.rand(6,4), index=dates, columns=list('ABCD'))
df
Out[5]:
A B C D
2016-01-26 0.903415 0.102206 0.171511 0.143382
2016-01-27 0.047119 0.859436 0.775962 0.320524
2016-01-28 0.862953 0.529486 0.832273 0.469585
2016-01-29 0.382351 0.419506 0.638357 0.635443
2016-01-30 0.220556 0.156135 0.028593 0.303569
2016-01-31 0.486773 0.454410 0.382029 0.247028

Une autre façon pour définir un dataframe et de nommer les colonnes :

In [6]:
df2 = pd.DataFrame({ 'A' : np.arange(10)*2,
    'B' : pd.Timestamp('20130102'),
    'C' : pd.Series(2.5,index=list(range(10))),
    'D' : np.array([5,3,6,2,9] * 2,dtype='int32'),
    'E' : pd.Categorical(["test","train","test","train","train","train","train","train","train","test"]),
    'F' : list('wiragnuopa') })
df2
Out[6]:
A B C D E F
0 0 2013-01-02 2.5 5 test w
1 2 2013-01-02 2.5 3 train i
2 4 2013-01-02 2.5 6 test r
3 6 2013-01-02 2.5 2 train a
4 8 2013-01-02 2.5 9 train g
5 10 2013-01-02 2.5 5 train n
6 12 2013-01-02 2.5 3 train u
7 14 2013-01-02 2.5 6 train o
8 16 2013-01-02 2.5 2 train p
9 18 2013-01-02 2.5 9 test a

Pour obtenir les dimensions du tableau :

In [7]:
df2.shape
Out[7]:
(10, 6)

Pour obtenir une liste des noms de variables :

In [8]:
list(df2)
Out[8]:
['A', 'B', 'C', 'D', 'E', 'F']

Voir les types des colonnes:

In [9]:
df2.dtypes
Out[9]:
A             int32
B    datetime64[ns]
C           float64
D             int32
E          category
F            object
dtype: object

Essayer les commandes suivantes :

In [10]:
df2.head()
Out[10]:
A B C D E F
0 0 2013-01-02 2.5 5 test w
1 2 2013-01-02 2.5 3 train i
2 4 2013-01-02 2.5 6 test r
3 6 2013-01-02 2.5 2 train a
4 8 2013-01-02 2.5 9 train g
In [11]:
df2.tail(3)
Out[11]:
A B C D E F
7 14 2013-01-02 2.5 6 train o
8 16 2013-01-02 2.5 2 train p
9 18 2013-01-02 2.5 9 test a
In [12]:
df.index
Out[12]:
DatetimeIndex(['2016-01-26', '2016-01-27', '2016-01-28', '2016-01-29',
               '2016-01-30', '2016-01-31'],
              dtype='datetime64[ns]', freq='D')
In [13]:
df2.index
Out[13]:
Int64Index([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='int64')
In [14]:
df.columns
Out[14]:
Index([u'A', u'B', u'C', u'D'], dtype='object')
In [15]:
df.values
Out[15]:
array([[ 0.90341466,  0.10220599,  0.17151104,  0.14338162],
       [ 0.0471187 ,  0.85943646,  0.77596193,  0.3205235 ],
       [ 0.8629532 ,  0.52948627,  0.83227276,  0.46958548],
       [ 0.38235072,  0.41950643,  0.63835695,  0.63544308],
       [ 0.22055612,  0.15613497,  0.02859272,  0.30356943],
       [ 0.48677341,  0.45441035,  0.38202853,  0.24702801]])
In [16]:
df2.values
Out[16]:
array([[0, Timestamp('2013-01-02 00:00:00'), 2.5, 5, 'test', 'w'],
       [2, Timestamp('2013-01-02 00:00:00'), 2.5, 3, 'train', 'i'],
       [4, Timestamp('2013-01-02 00:00:00'), 2.5, 6, 'test', 'r'],
       [6, Timestamp('2013-01-02 00:00:00'), 2.5, 2, 'train', 'a'],
       [8, Timestamp('2013-01-02 00:00:00'), 2.5, 9, 'train', 'g'],
       [10, Timestamp('2013-01-02 00:00:00'), 2.5, 5, 'train', 'n'],
       [12, Timestamp('2013-01-02 00:00:00'), 2.5, 3, 'train', 'u'],
       [14, Timestamp('2013-01-02 00:00:00'), 2.5, 6, 'train', 'o'],
       [16, Timestamp('2013-01-02 00:00:00'), 2.5, 2, 'train', 'p'],
       [18, Timestamp('2013-01-02 00:00:00'), 2.5, 9, 'test', 'a']], dtype=object)
In [17]:
df.describe()
Out[17]:
A B C D
count 6.000000 6.000000 6.000000 6.000000
mean 0.483861 0.420197 0.471454 0.353255
std 0.343547 0.274552 0.330109 0.174375
min 0.047119 0.102206 0.028593 0.143382
25% 0.261005 0.221978 0.224140 0.261163
50% 0.434562 0.436958 0.510193 0.312046
75% 0.768908 0.510717 0.741561 0.432320
max 0.903415 0.859436 0.832273 0.635443
In [18]:
df2.describe()
Out[18]:
A C D
count 10.000000 10.0 10.000000
mean 9.000000 2.5 5.000000
std 6.055301 0.0 2.581989
min 0.000000 2.5 2.000000
25% 4.500000 2.5 3.000000
50% 9.000000 2.5 5.000000
75% 13.500000 2.5 6.000000
max 18.000000 2.5 9.000000

Accès aux éléments d'un tableau

On utilise les noms des colonnes entre crochets, pour sélectionner des colonnes :

In [19]:
df['C']
Out[19]:
2016-01-26    0.171511
2016-01-27    0.775962
2016-01-28    0.832273
2016-01-29    0.638357
2016-01-30    0.028593
2016-01-31    0.382029
Freq: D, Name: C, dtype: float64
In [20]:
df[['A','C']]
Out[20]:
A C
2016-01-26 0.903415 0.171511
2016-01-27 0.047119 0.775962
2016-01-28 0.862953 0.832273
2016-01-29 0.382351 0.638357
2016-01-30 0.220556 0.028593
2016-01-31 0.486773 0.382029

On note qu'une colonne d'un dataframe est une série :

In [21]:
type(df['C'])
Out[21]:
pandas.core.series.Series

Par des entiers entre crochets ou en utilisant les indices des lignes, on accède aux lignes :

In [22]:
df[0:2]
Out[22]:
A B C D
2016-01-26 0.903415 0.102206 0.171511 0.143382
2016-01-27 0.047119 0.859436 0.775962 0.320524
In [23]:
df['20160126':'20160127']
Out[23]:
A B C D
2016-01-26 0.903415 0.102206 0.171511 0.143382
2016-01-27 0.047119 0.859436 0.775962 0.320524
In [24]:
df2[df2['E']=='test']
Out[24]:
A B C D E F
0 0 2013-01-02 2.5 5 test w
2 4 2013-01-02 2.5 6 test r
9 18 2013-01-02 2.5 9 test a

Pour une sélection plus sophistiquée d'éléments d'un dataframe, il faut utiliser les fonctions .loc, .iloc ou .ix

  • .loc quand on utilise les indices des lignes et les labels des colonnes

  • .iloc quand on utilise des entiers pour sélectionner les lignes et colonnes

  • .ix quand on mélange des entiers et des labels

Jouer avec les exemples suivants pour bien comprendre la différence de ces méthodes (p.ex. dans la première instruction remplacez .loc par .iloc ou .ix et vérifiez si ça marche encore).

In [25]:
df.loc['20160126':'20160127',['A','B']]
Out[25]:
A B
2016-01-26 0.903415 0.102206
2016-01-27 0.047119 0.859436
In [26]:
df2.iloc[0:2,0:2]
Out[26]:
A B
0 0 2013-01-02
1 2 2013-01-02
In [27]:
df.ix[0:2,['A','B']]
Out[27]:
A B
2016-01-26 0.903415 0.102206
2016-01-27 0.047119 0.859436

Les trois méthodes acceptent également un masque booléan (de True/False) pour la sélection.

In [28]:
df.loc[df['A']>.6,['B','D']]
Out[28]:
B D
2016-01-26 0.102206 0.143382
2016-01-28 0.529486 0.469585
In [29]:
df2.loc[df2['E']=='test','A']
Out[29]:
0     0
2     4
9    18
Name: A, dtype: int32

Ajouter une colonne à un tableau

In [30]:
df
Out[30]:
A B C D
2016-01-26 0.903415 0.102206 0.171511 0.143382
2016-01-27 0.047119 0.859436 0.775962 0.320524
2016-01-28 0.862953 0.529486 0.832273 0.469585
2016-01-29 0.382351 0.419506 0.638357 0.635443
2016-01-30 0.220556 0.156135 0.028593 0.303569
2016-01-31 0.486773 0.454410 0.382029 0.247028
In [31]:
df['K'] = np.pi
df
Out[31]:
A B C D K
2016-01-26 0.903415 0.102206 0.171511 0.143382 3.141593
2016-01-27 0.047119 0.859436 0.775962 0.320524 3.141593
2016-01-28 0.862953 0.529486 0.832273 0.469585 3.141593
2016-01-29 0.382351 0.419506 0.638357 0.635443 3.141593
2016-01-30 0.220556 0.156135 0.028593 0.303569 3.141593
2016-01-31 0.486773 0.454410 0.382029 0.247028 3.141593

Fonctions de base pour tableaux

La plupart des fonctions que nous avons vues pour les séries s'appliquent également aux dataframes.

Trier un tableau

In [32]:
df2.sort_index(axis=0, ascending=False)
Out[32]:
A B C D E F
9 18 2013-01-02 2.5 9 test a
8 16 2013-01-02 2.5 2 train p
7 14 2013-01-02 2.5 6 train o
6 12 2013-01-02 2.5 3 train u
5 10 2013-01-02 2.5 5 train n
4 8 2013-01-02 2.5 9 train g
3 6 2013-01-02 2.5 2 train a
2 4 2013-01-02 2.5 6 test r
1 2 2013-01-02 2.5 3 train i
0 0 2013-01-02 2.5 5 test w
In [33]:
df2.sort_index(axis=1, ascending=False)
Out[33]:
F E D C B A
0 w test 5 2.5 2013-01-02 0
1 i train 3 2.5 2013-01-02 2
2 r test 6 2.5 2013-01-02 4
3 a train 2 2.5 2013-01-02 6
4 g train 9 2.5 2013-01-02 8
5 n train 5 2.5 2013-01-02 10
6 u train 3 2.5 2013-01-02 12
7 o train 6 2.5 2013-01-02 14
8 p train 2 2.5 2013-01-02 16
9 a test 9 2.5 2013-01-02 18
In [34]:
df2.sort_values(by='F')
Out[34]:
A B C D E F
3 6 2013-01-02 2.5 2 train a
9 18 2013-01-02 2.5 9 test a
4 8 2013-01-02 2.5 9 train g
1 2 2013-01-02 2.5 3 train i
5 10 2013-01-02 2.5 5 train n
7 14 2013-01-02 2.5 6 train o
8 16 2013-01-02 2.5 2 train p
2 4 2013-01-02 2.5 6 test r
6 12 2013-01-02 2.5 3 train u
0 0 2013-01-02 2.5 5 test w

Importer des données d'un fichier .csv

Comme pour les séries, on utilise la fonction pd.read_csv pour importer un tableau de données.

Pour cela, il faut que les données soient représentées sous forme d'un tablau dans le fichier csv, c'est-à-dire que les colonnes sont les variables et les lignes les observations sur différents individus.

Le premier argument de la fonction pd.read_csv est le chemin vers le fichier ou l'URL.

Si le symbole qui sépare les valeurs dans le fichier n'est pas la virgule, il faut précsier le séparateur dans l'appel de pd.read_csv. P. ex. si le séparateur est la tabulation, il faut écrire

pd.read_csv(filepath, sep='\t')

Exercice. Poussins

Nous allons analyser des données sur des poussins. Il s'agit de poussins qui suivent différents régimes alimentaires et qui sont pesés régulièrement.

  1. Importer les données chicken.csv disponible à l'adresse http://www.proba.jussieu.fr/pageperso/rebafka/chicken.csv

  2. Combien de variables contient le tableau ? Déterminer le nombre de mesures effectuées et le nombre de poussins dans l'étude ? Combien de régimes y-a t'il ? Déterminer le nombre de poussins par régime. Quelle période est couverte par les observations (combien de jours) ? Est-ce que tous les poussins sont suivis jusqu'à la fin ?

  3. Combien de poussins ont un poids final supérieur à 250g ? Inférieur à 200g ?

  4. Déterminer le poids maximal/minimal à la naissance/au 10e jours/à la fin. Est-ce toujours le même poussin qui est le plus/moins lourd ?

  5. Calculer le poids moyen des poussins à la naissance et à la fin (au 21e jour) (tous les poussins confondus).

  6. Calculer le poids moyen des poussins à la naissance et à la fin (au 21e jour) par régime. Commenter les résultats.

  7. Calculer l’écart-type du poids des poussins à la naissance et à la fin (au 21e jour) par régime. Commenter les résultats.