Vous êtes sur la page 1sur 16

3 Pandas

Pandas est un package Python populaire pour la science des données, et pour une bonne raison: il offre des
structures de données puissantes, expressives et flexibles qui facilitent la manipulation et l'analyse des
données, entre autres. Le DataFrame est l'une de ces structures.

Que sont les DataFrames Pandas?


Avant de commencer, récapitulons brièvement ce que sont les DataFrames.

Ceux qui sont familiers avec R connaissent la data frame comme un moyen de stocker des données dans
des grilles rectangulaires qui peuvent facilement être vues. Chaque ligne de ces grilles correspond aux
mesures ou aux valeurs d'une instance, tandis que chaque colonne est un vecteur contenant des données
pour une variable spécifique. Cela signifie que les lignes de données n'ont pas besoin de contenir, mais
peuvent contenir, le même type de valeurs: elles peuvent être numériques, caractères, logiques, etc.

Désormais, les DataFrames en Python sont très similaires: ils sont fournis avec la bibliothèque Pandas et ils
sont définis comme des structures de données étiquetées bidimensionnelles avec des colonnes de types
potentiellement différents.

En général, vous pourriez dire que le Pandas DataFrame se compose de trois composants principaux: les
données, l'index et les colonnes.

Avec une définition élargie, les données peuvent être contenu dans :

un Pandas DataFrame

une Pandas Series : un tableau étiqueté unidimensionnel capable de contenir n'importe quel type

de données avec des étiquettes d'axe ou un index. Un exemple d'objet Series est une colonne d'un

DataFrame.

NumPy ndarray

lists, dictionaries or Series.

Outre les données, vous pouvez également spécifier les noms d'index et de colonne de votre DataFrame.
L'index, d'une part, indique la différence entre les lignes, tandis que les noms de colonnes indiquent la
différence entre les colonnes. Vous verrez plus tard que ces deux composants du DataFrame vous seront
utiles lorsque vous manipulerez vos données.

Pour utiliser des pandas, vous commencerez généralement par la ligne de code suivante. (On suppose que
numpy est déjà importé, sinon "import numpy as np" )

import pandas as pd
3.1 Creation des données

Il existe deux objets de base dans les pandas: le DataFrame et la Serie

3.1.1 DataFrame

Un DataFrame est une table. Il contient un tableau d'entrées individuelles, dont chacune a une certaine
valeur. Chaque entrée correspond à une ligne (ou enregistrement) et une colonne.

Par exemple, considérez le DataFrame simple suivant:

pd.DataFrame({'Yes': [50, 21], 'No': [131, 2]})

Yes No

0 50 131

1 21 2

Dans cet exemple, l'entrée «0, No» a la valeur de 131. L'entrée «0, Yes» a une valeur de 50 et ainsi de suite

Les entrées DataFrame ne sont pas limitées aux entiers. Par exemple, voici un DataFrame dont les valeurs
sont des chaînes:

pd.DataFrame({'Bob': ['I liked it.', 'It was awful.'], 'Sue': ['Pretty good.',
'Bland.']})

Bob Sue

0 I liked it. Pretty good.

1 It was awful. Bland.

Nous utilisons le constructeur pd.DataFrame () pour générer ces objets DataFrame. La syntaxe pour en
déclarer un nouveau est un dictionnaire dont les clés sont les noms de colonnes (Bob et Sue dans cet
exemple), et dont les valeurs sont une liste d'entrées. C'est la manière standard de construire un nouveau
DataFrame, et celui que vous êtes le plus susceptible de rencontrer.
Le constructeur dictionnaire-liste attribue des valeurs aux étiquettes de colonne, mais utilise simplement un
nombre croissant de 0 (0, 1, 2, 3, ...) pour les étiquettes de ligne. Parfois, c'est correct, mais souvent, nous
voudrons attribuer ces étiquettes nous-mêmes.

Une liste des étiquettes de ligne utilisées dans un DataFrame est connue sous le nom d'index. Nous pouvons
lui attribuer des valeurs en utilisant un paramètre d'index dans notre constructeur:

pd.DataFrame({'Bob': ['I liked it.', 'It was awful.'],


'Sue': ['Pretty good.', 'Bland.']},
index=['Product A', 'Product B'])

Bob Sue

Product A I liked it. Pretty good.

Product B It was awful. Bland.

3.1.2 Series

Une série, en revanche, est une séquence de valeurs de données. Si un DataFrame est une table, une série
est une liste. Et en fait, vous pouvez en créer une avec rien de plus qu'une liste:

pd.Series([1, 2, 3, 4, 5])

Output:

0 1
1 2
2 3
3 4
4 5
dtype: int64

Une série est une seule colonne d'un DataFrame. Vous pouvez donc attribuer des valeurs de colonne à la
série de la même manière qu'auparavant, à l'aide d'un paramètre d'index. Cependant, une série n'a pas de
nom de colonne, elle n'en possède qu'un seul name :

pd.Series([30, 35, 40], index=['2015 Sales', '2016 Sales', '2017 Sales'],


name='Product A')
Output:

2015 Sales 30
2016 Sales 35
2017 Sales 40
Name: Product A, dtype: int64

La série et le DataFrame sont intimement liés. Il est utile de penser qu’un DataFrame n’est en fait qu’un
ensemble de séries «collées ensemble».

Lecture du fichier de données:

Il est pratique de pouvoir créer un DataFrame ou une série à la main. Mais, la plupart du temps, nous ne
créerons pas nos propres données à la main. Nous travaillerons plutôt avec des données qui existent déjà.

Les données peuvent être stockées dans un certain nombre de formes et de formats différents. Le plus
élémentaire d'entre eux est de loin le modeste fichier CSV. Lorsque vous ouvrez un fichier CSV, vous obtenez
quelque chose qui ressemble à ceci:

Product A,Product B,Product C,


30,21,9,
35,34,1,
41,11,11

Un fichier CSV est donc un tableau de valeurs séparées par des virgules, d'où le nom Comma-Separated
Values", or CSV.

Prenez un fichier csv, renommez par exemple "sample.csv",

Essayez le bout de code suivant:

samples = pd.read_csv("sample.csv")

wine_reviews.shape

wine_reviews.head()

Vous aurez quelque chose similaire à


3.2 Indexing, Selecting & Assigning

Les informations d'étiquetage des axes dans les objets pandas servent à plusieurs fins:

Identifie les données (c'est-à-dire fournit des métadonnées) à l'aide d'indicateurs connus, importants

pour l'analyse, la visualisation et l'affichage de la console interactive.

Permet l'alignement automatique et explicite des données.

Permet d'obtenir et de définir intuitivement des sous-ensembles de l'ensemble de données.

3.2.1 Accesseurs natifs

Considérez ce DataFrame: samples

samples
En Python, nous pouvons accéder à la propriété d'un objet en y accédant en tant qu'attribut. Un objet
book , par exemple, peut avoir une propriété title , à laquelle nous pouvons accéder en appelant
book.title . Les colonnes d'un pandas DataFrame fonctionnent à peu près de la même manière.

Par conséquent, pour accéder à la propriété country de samples, nous pouvons utiliser:

samples.country

output:

0 Italy
1 Portugal
...
129969 France
129970 France
Name: country, Length: 129971, dtype: object

Si nous avons un dictionnaire Python, nous pouvons accéder à ses valeurs en utilisant l'opérateur
d'indexation ( [] ). Nous pouvons faire la même chose avec des colonnes dans un DataFrame:

reviews['country']

Output:
0 Italy
1 Portugal
...
129969 France
129970 France
Name: country, Length: 129971, dtype: object

Ce sont les deux façons de sélectionner une série spécifique dans un DataFrame. Aucun d'eux n'est plus ou
moins syntaxiquement valide que l'autre, mais l'opérateur d'indexation [] a l'avantage de pouvoir gérer les
noms de colonnes avec des caractères réservés.

Une série de pandas ne ressemble-t-elle pas à un dictionnaire sophistiqué? C'est à peu près le cas, il n'est
donc pas surprenant que, pour explorer une valeur spécifique unique, nous n'utilisions qu'une fois de plus
l'opérateur d'indexation []:

samples['country'][0]

Output:

'Italy'

3.3 Indexing dans pandas

pandas a ses propres opérateurs d'accesseurs, loc et iloc . Les deux loc et iloc sont row-first, column-
second. C'est le contraire de ce que nous faisons en Python natif, qui est column-first, row-second.

3.3.1 Index-based selection

sélectionner des données en fonction de leur position numérique dans les données. iloc suit ce
paradigme.

Pour sélectionner la première ligne de données dans un DataFrame, nous pouvons utiliser ce qui suit:

samples.iloc[0]

Output:

country Italy
description Aromas include tropical fruit, broom, brimston...
...
variety White Blend
winery Nicosia
Name: 0, Length: 13, dtype: object
Pour obtenir une colonne avec iloc, nous pouvons faire ce qui suit:

samples.iloc[:, 0]

Output:

0 Italy
1 Portugal
...
129969 France
129970 France
Name: country, Length: 129971, dtype: object

Pour sélectionner la colonne de pays uniquement à partir de la première, deuxième et troisième lignes,
nous ferions:

samples.iloc[:3, 0]

Output:

0 Italy
1 Portugal
2 US
Name: country, dtype: object

Nous pouvons aussi faire

samples.iloc[1:3, 0]

Output:

1 Portugal
2 US
Name: country, dtype: object

reviews.iloc[[0, 1, 2], 0]

Output:
0 Italy
1 Portugal
2 US
Name: country, dtype: object

Enfin, il convient de savoir que les nombres négatifs peuvent être utilisés dans la sélection.

samples.iloc[-5:]

3.3.2 Label-based selection

Dans ce paradigme, c'est la valeur de l'indice de données, et non sa position, qui compte.

Par exemple:

samples.loc[0, 'country']

Output:

'Italy'

iloc est conceptuellement plus simple que loc car il ignore les indices de l'ensemble de données.
Lorsque nous utilisons iloc , nous traitons l'ensemble de données comme une grande matrice (une liste
de listes), dans laquelle nous devons indexer par position. loc , en revanche, utilise les informations
contenues dans les indices pour faire son travail. Étant donné que votre ensemble de données a
généralement des indices significatifs, il est généralement plus facile de faire les choses en utilisant loc à
la place

samples.loc[:, ['taster_name', 'taster_twitter_handle', 'points']]


3.4 Conditional selection

samples.country == 'Italy'

Output:

0 True
1 False
...
129969 False
129970 False
Name: country, Length: 129971, dtype: bool

Cette opération a produit une série de valeurs booléennes Vrai / Faux en fonction du pays de chaque
enregistrement. Ce résultat peut ensuite être utilisé à l'intérieur de loc pour sélectionner les données
pertinentes:

samples.loc[samples.country == 'Italy']

Nous pouvons utiliser l'esperluette (&) ou le tube (|) pour réunir les deux questions:

samples.loc[(samples.country == 'Italy') & (samples.points >= 90)]


samples.loc[(samples.country == 'Italy') | (samples.points >= 90)]

Nous avons également trois méthodes qui nous aident à sélectionner les données
#sélectionner des vins uniquement d'Italie ou de France:
samples.loc[samples.country.isin(['Italy', 'France'])]

#Ces méthodes vous permettent de mettre en évidence les valeurs qui sont (ou ne
sont pas) vides (NaN).
samples.loc[samples.price.isnull()]
samples.loc[samples.price.notnull()]

3.5 Assigner des données

En plus de l'assignation classique d'une valeur à une position spécifique, vous pouvez attribuer une valeur
constante

reviews['critic'] = 'everyone'
reviews['critic']

Output:

0 everyone
1 everyone
...
129969 everyone
129970 everyone
Name: critic, Length: 129971, dtype: object

ou avec un itérable de valeurs:

reviews['index_backwards'] = range(len(reviews), 0, -1)


reviews['index_backwards']

Output:

0 129971
1 129970
...
129969 2
129970 1
Name: index_backwards, Length: 129971, dtype: int64
3.6 Dtypes

Le type de données d'une colonne dans un DataFrame ou une Series est appelé dtype

samples.price.dtype

dtype('float64')

la propriété dtypes renvoie le dtype de chaque colonne du DataFrame:

samples.dtypes

country object
description object
...
variety object
winery object
Length: 13, dtype: object

3.7 Missing data

Les valeurs manquantes des entrées reçoivent la valeur NaN, abréviation de "Not a Number". Pour des
raisons techniques, ces valeurs NaN sont toujours de type float64 .

samples[pd.isnull(samples.country)]
Le remplacement des valeurs manquantes est une opération courante. Pandas fournit une méthode très
pratique pour résoudre ce problème: fillna() . Par exemple, nous pouvons simplement remplacer
chaque NaN par un "Inconnu":

reviews.region_2.fillna("Unknown")

Output:

0 Unknown
1 Unknown
...
129969 Unknown
129970 Unknown
Name: region_2, Length: 129971, dtype: object

Alternativement, nous pouvons avoir une valeur non nulle que nous aimerions remplacer.

samples.taster_twitter_handle.replace("valueToReject", "newValueToKeep")
4 Traitement des données avec Pandas

4.1 Summary functions

Toute les méthodes dans cette section sont applicables à la fois pour une série et une dataframe

samples.points.describe()

Output:

count 129971.000000
mean 88.447138
...
75% 91.000000
max 100.000000
Name: points, Length: 8, dtype: float64

Par exemple, pour voir la moyenne des points attribués, nous pouvons utiliser la fonction mean ():

samples.points.mean()

Output:

88.44713820775404

Pour voir une liste de valeurs uniques, nous pouvons utiliser la fonction unique ():

samples.taster_name.unique()

Output:

array(['Kerin O’Keefe', 'Roger Voss', 'Paul Gregutt',


'Alexander Peartree', 'Michael Schachner', 'Anna Lee C. Iijima',
'Virginie Boone', 'Matt Kettmann', nan, 'Sean P. Sullivan',
'Jim Gordon', 'Joe Czerwinski', 'Anne Krebiehl\xa0MW',
'Lauren Buzzeo', 'Mike DeSimone', 'Jeff Jenssen',
'Susan Kostrzewa', 'Carrie Dykes', 'Fiona Adams',
'Christina Pickard'], dtype=object)
Pour voir une liste de valeurs uniques et leur fréquence d'apparition dans l'ensemble de données, nous
pouvons utiliser la méthode value_counts ():

samples.taster_name.value_counts()

Output:

Roger Voss 25514


Michael Schachner 15134
...
Fiona Adams 27
Christina Pickard 6
Name: taster_name, Length: 19, dtype: int64

4.2 Map() et apply()

Map est un terme, emprunté aux mathématiques, pour une fonction qui prend un ensemble de valeurs et
les «mappe» à un autre ensemble de valeurs. En science des données, nous avons souvent besoin de créer
de nouvelles représentations à partir de données existantes ou de transformer des données. Maps sont ce
qui gère ce travail, ce qui les rend extrêmement importantes pour faire votre travail!

Il existe deux façon de mappage que vous utiliserez souvent.

Par exemple, supposons que nous voulions remanier les scores moyens des vins reçus à 0. Nous pouvons le
faire comme suit:

sample_points_mean = samples.points.mean()
samples.points.map(lambda p: p - sample_points_mean)

Output:

0 -1.447138
1 -1.447138
...
129969 1.552862
129970 1.552862
Name: points, Length: 129971, dtype: float64

La fonction que vous transmettez à map () doit attendre une valeur unique de la série et renvoyer une
version transformée de cette valeur. Map () renvoie une nouvelle série dans laquelle toutes les valeurs ont
été transformées par votre fonction.
apply () est la méthode équivalente si nous voulons transformer un DataFrame entier en appelant une
méthode personnalisée sur chaque ligne(avec axis='columns' sinon axis='index' pour transformer chaque
colonne).

sample_points_mean = samples.points.mean()
def remean_points(row):
row.points = row.points - review_points_mean
return row

samples.apply(remean_points, axis='columns')


Notez que map () et apply () renvoient respectivement de nouveaux Series et DataFrames
transformés. Ils ne modifient pas les données d'origine sur lesquelles ils sont appelés

Nous pouvons aussi proposer une solution comme la façon du traitement de matrice dans Numpy :

Avec le built-in opération, nous avons:

sample_points_mean = samples.points.mean()
samples.points - sample_points_mean

Output:

Vous aimerez peut-être aussi