In [0]:
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Présentation rapide de Pandas

Objectifs d'apprentissage :

  • Introduction aux structures de données DataFrame et Series de la bibliothèque Pandas
  • Accéder aux données et les manipuler dans une structure DataFrame et Series
  • Importer des données d'un fichier CSV dans un DataFrame Pandas
  • Réindexer un DataFrame pour mélanger les données

Pandas est une API d'analyse de données orientée colonnes. C'est un excellent outil pour manipuler et analyser des données d'entrée. Beaucoup de frameworks d'apprentissage automatique acceptent les structures de données Pandas en entrée. Il faudrait des pages et des pages pour présenter de manière exhaustive l'API Pandas, mais les concepts fondamentaux sont relativement simples. Aussi, nous avons décidé de vous les exposer ci-dessous. Pour une description plus complète, vous pouvez consulter le site de documentation de Pandas, sur lequel vous trouverez de multiples informations ainsi que de nombreux didacticiels.

Concepts de base

La ligne de code suivante permet d'importer l'API pandas et d'afficher sa version :


In [0]:
from __future__ import print_function

import pandas as pd
pd.__version__

On distingue deux grandes catégories de structures de données Pandas :

  • Le DataFrame, un tableau relationnel de données, avec des lignes et des colonnes étiquetées
  • La Series, constituée d'une seule colonne. Un DataFrame contient une ou plusieurs Series, chacune étant étiquetée.

Le DataFrame est une abstraction fréquemment utilisée pour manipuler des données. Spark et R proposent des implémentations similaires.

Pour créer une Series, vous pouvez notamment créer un objet Series. Par exemple :


In [0]:
pd.Series(['San Francisco', 'San Jose', 'Sacramento'])

Il est possible de créer des objets DataFrame en transmettant un dictionnaire qui met en correspondance les noms de colonnes (des chaînes de caractères) avec leur Series respective. Lorsque la longueur de la Series ne correspond pas, les valeurs manquantes sont remplacées par des valeurs NA/NaN spéciales. Exemple :


In [0]:
city_names = pd.Series(['San Francisco', 'San Jose', 'Sacramento'])
population = pd.Series([852469, 1015785, 485199])

pd.DataFrame({ 'City name': city_names, 'Population': population })

Le plus souvent, vous chargez un fichier entier dans un DataFrame. Dans l'exemple qui suit, le fichier chargé contient des données immobilières pour la Californie. Exécutez la cellule suivante pour charger les données et définir les caractéristiques :


In [0]:
california_housing_dataframe = pd.read_csv("https://download.mlcc.google.com/mledu-datasets/california_housing_train.csv", sep=",")
california_housing_dataframe.describe()

Dans l'exemple ci-dessus, la méthode DataFrame.describe permet d'afficher des statistiques intéressantes concernant un DataFrame. La fonction DataFrame.head est également utile pour afficher les premiers enregistrements d'un DataFrame :


In [0]:
california_housing_dataframe.head()

Autre fonction puissante de Pandas : la représentation graphique. Avec DataFrame.hist, par exemple, vous pouvez vérifier rapidement la façon dont les valeurs d'une colonne sont distribuées :


In [0]:
california_housing_dataframe.hist('housing_median_age')

Accéder aux données

L'accès aux données d'un DataFrame s'effectue au moyen d'opérations de liste ou de dictionnaire Python courantes :


In [0]:
cities = pd.DataFrame({ 'City name': city_names, 'Population': population })
print(type(cities['City name']))
cities['City name']

In [0]:
print(type(cities['City name'][1]))
cities['City name'][1]

In [0]:
print(type(cities[0:2]))
cities[0:2]

Pandas propose en outre une API extrêmement riche, avec des fonctions avancées d'indexation et de sélection, que nous ne pouvons malheureusement pas aborder ici dans le détail.

Manipuler des données

Il est possible d'effectuer des opérations arithmétiques de base de Python sur les Series. Par exemple :


In [0]:
population / 1000.

NumPy est un kit d'outils de calculs scientifiques populaire. Les Series Pandas peuvent faire office d'arguments pour la plupart des fonctions NumPy :


In [0]:
import numpy as np

np.log(population)

La méthode Series.apply convient pour les transformations à une colonne plus complexes. Comme la fonction map de Python, elle accepte en argument une fonction lambda, appliquée à chaque valeur.

L'exemple ci-dessous permet de créer une Series signalant si la population dépasse ou non un million d'habitants :


In [0]:
population.apply(lambda val: val > 1000000)

La modification des DataFrames est également très simple. Ainsi, le code suivant permet d'ajouter deux Series à un DataFrame existant :


In [0]:
cities['Area square miles'] = pd.Series([46.87, 176.53, 97.92])
cities['Population density'] = cities['Population'] / cities['Area square miles']
cities

Exercice n° 1

Modifiez le tableau cities en ajoutant une colonne booléenne qui prend la valeur True si et seulement si les deux conditions suivantes sont remplies :

  • La ville porte le nom d'un saint.
  • La ville s'étend sur plus de 50 miles carrés.

Remarque : Pour combiner des Series booléennes, utilisez des opérateurs de bits, pas les opérateurs booléens classiques. Par exemple, pour le ET logique, utilisez & au lieu de and.

Astuce : En espagnol, "San" signifie "saint".


In [0]:
# Your code here

Solution

Cliquez ci-dessous pour afficher la solution.


In [0]:
cities['Is wide and has saint name'] = (cities['Area square miles'] > 50) & cities['City name'].apply(lambda name: name.startswith('San'))
cities

Index

Les objets Series et DataFrame définissent également une propriété index, qui affecte un identifiant à chaque élément d'une Series ou chaque ligne d'un DataFrame.

Par défaut, Pandas affecte les valeurs d'index en suivant l'ordre des données source. Ces valeurs ne varient pas par la suite ; elles restent inchangées en cas de réagencement des données.


In [0]:
city_names.index

In [0]:
cities.index

Appelez DataFrame.reindex pour réorganiser manuellement les lignes. Le code suivant, par exemple, revient à trier les données par nom de ville :


In [0]:
cities.reindex([2, 0, 1])

La réindexation est un excellent moyen de mélanger (organiser aléatoirement) les données d'un DataFrame. Dans l'exemple ci-dessous, l'index de type tableau est transmis à la fonction NumPy random.permutation, qui mélange les valeurs. En appelant reindex avec ce tableau mélangé, nous mélangeons également les lignes du DataFrame. Exécutez plusieurs fois la cellule suivante !


In [0]:
cities.reindex(np.random.permutation(cities.index))

Pour en savoir plus, consultez la documentation relative aux index.

Exercice n° 2

La méthode reindex autorise les valeurs d'index autres que celles associées au DataFrame d'origine. Voyez ce qu'il se passe lorsque vous utilisez ce type de valeurs ! Pourquoi est-ce autorisé à votre avis ?


In [0]:
# Your code here

Solution

Cliquez ci-dessous pour afficher la solution.

Lorsque le tableau d'entrée reindex contient des valeurs d'index ne faisant pas partie de la liste des index du DataFrame d'origine, reindex ajoute des lignes pour ces index \'manquants\' et insère la valeur NaN dans les colonnes correspondantes :


In [0]:
cities.reindex([0, 4, 5, 2])

Ce comportement est souhaitable, car les index sont souvent des chaînes de caractères extraites des données réelles. La documentation Pandas sur la fonction reindex inclut un exemple avec des noms de navigateurs comme valeurs d'index).

Dans ce cas, autoriser les index \'manquants\' facilite la réindexation à l'aide d'une liste externe, car vous n'avez pas à vous préoccuper de l'intégrité des données d'entrée.