Cours

Savoir créer des graphiques à la fois lisibles et sophistiqués est essentiel pour réussir en data science. Les visualisations sont un excellent moyen de raconter l'histoire cachée dans vos données. Elles mettent en évidence les relations et révèlent des informations que l'œil humain perçoit mais que de simples chiffres ne suffisent pas à transmettre. Et qu'y a-t-il de mieux encore pour l'analyse de données que des visualisations statiques ? Des visualisations interactives !
Malheureusement, lorsque l'on débute, la tâche peut sembler intimidante. Python et R proposent tous deux une large palette d'outils et d'astuces pour vous y aider. Dans ce tutoriel, nous allons vous présenter Altair. Avec Altair, vous pourrez créer des visualisations pertinentes, élégantes et efficaces en quelques lignes de code et en un rien de temps. Allons-y !
Qu'est-ce qu'Altair ?
Altair est une bibliothèque Python conçue pour la visualisation statistique. Elle est de nature déclarative (nous reviendrons sur cette notion plus loin). Elle s'appuie sur Vega et Vega-Lite, deux grammaires de visualisation qui permettent de décrire l'apparence visuelle et le comportement interactif d'un graphique dans un format JSON.
API impératives vs déclaratives
Comme mentionné plus haut, Python met déjà à votre disposition de très bons outils et bibliothèques pour la visualisation de données, dont plusieurs gèrent l'interactivité. Alors, qu'est-ce qui distingue Altair ?
La réponse tient à sa nature déclarative, par opposition aux API impératives.
Avec des API impératives, vous devez vous concentrer sur « comment faire » plutôt que sur « ce que vous voulez faire ». Vous pensez davantage au code nécessaire pour produire le graphique et vous précisez manuellement les étapes de tracé : limites des axes, taille, rotation, légendes, etc.
En tant que data scientist, Altair vous permet de consacrer votre temps et vos efforts à vos données — les comprendre, les analyser et les visualiser — plutôt qu'au code requis. Concrètement, vous définissez les données et le résultat attendu (l'apparence finale de la visualisation), et Altair effectue automatiquement les manipulations nécessaires.
Installation
Dans ce tutoriel, nous utiliserons un jeu de données d'exemple issu de Vega datasets. Pour installer Altair ainsi que les jeux de données Vega, tapez la commande suivante dans votre console :
$ pip install altair vega_datasets
Si vous utilisez le gestionnaire de paquets conda, l'équivalent est :
$ conda install -c conda-forge altair vega_datasets
Ensuite, ouvrez votre Jupyter Notebook et importez Altair pour démarrer. Pour en savoir plus sur Jupyter Notebook, consultez le guide définitif de Jupyter Notebook de DataCamp.
Données
Maintenant qu'Altair et les jeux de données Vega sont installés, chargeons des données. Commencez par les imports suivants :
import pandas as pd
import altair as alt
Pourquoi importer pandas ?
Parce que la gestion des données dans Altair repose sur le DataFrame pandas, ce qui signifie que vous pouvez manipuler les données de la même manière que dans un DataFrame pandas.
Même si Altair stocke les données en interne sous forme de DataFrame pandas, il existe plusieurs façons de fournir les données :
- sous forme de DataFrame pandas
- sous forme d'objet Data ou apparenté (par ex. UrlData, InlineData, NamedData)
- sous forme d'URL vers un fichier texte au format JSON ou CSV
- sous forme d'objet prenant en charge l'interface geo_interface (p. ex. GeoDataFrame Geopandas, géométries Shapely, objets GeoJSON)
Jeu de données Movies
Dans ce tutoriel, nous allons travailler avec le Movies Dataset du catalogue Vega. Ce jeu de données, ou des variantes similaires sur les films, est très populaire dans la communauté data science, notamment pour les moteurs de recommandation. Ici, nous allons simplement l'analyser à l'aide de visualisations avec Altair.
Le jeu de données contient des informations sur les films : titre, recettes aux États-Unis et dans le monde, budget de production, genre, notes IMDB et Rotten Tomatoes, etc. Nous n'utiliserons pas toutes les colonnes, mais seulement quelques-unes pour comprendre le fonctionnement d'Altair comme outil de visualisation.
Passons à la récupération du jeu de données et effectuons quelques analyses simples pour mieux le comprendre.
# Importing the Vega Dataset
from vega_datasets import data as vega_data
movies_df = pd.read_json(vega_data.movies.url)
# Checking the type of data that we get
print("movies_df is of the type: ", type(movies_df))
print("movies_df: ", movies_df.shape)
movies_df is of the type: <class 'pandas.core.frame.DataFrame'>
movies_df: (3201, 16)
Comme vous l'avez vu, movies_df est bien un DataFrame pandas et contient 3201 films (lignes) avec 16 caractéristiques (colonnes) chacun. Examinons-en le contenu.
movies_df.head(5)
| Title | US_Gross | Worldwide_Gross | US_DVD_Sales | Production_Budget | Release_Date | MPAA_Rating | Running_Time_min | Distributor | Source | Major_Genre | Creative_Type | Director | Rotten_Tomatoes_Rating | IMDB_Rating | IMDB_Votes | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | The Land Girls | 146083.0 | 146083.0 | NaN | 8000000.0 | Jun 12 1998 | R | NaN | Gramercy | None | None | None | None | NaN | 6.1 | 1071.0 |
| 1 | First Love, Last Rites | 10876.0 | 10876.0 | NaN | 300000.0 | Aug 07 1998 | R | NaN | Strand | None | Drama | None | None | NaN | 6.9 | 207.0 |
| 2 | I Married a Strange Person | 203134.0 | 203134.0 | NaN | 250000.0 | Aug 28 1998 | None | NaN | Lionsgate | None | Comedy | None | None | NaN | 6.8 | 865.0 |
| 3 | Let's Talk About Sex | 373615.0 | 373615.0 | NaN | 300000.0 | Sep 11 1998 | None | NaN | Fine Line | None | Comedy | None | None | 13.0 | NaN | NaN |
| 4 | Slam | 1009819.0 | 1087521.0 | NaN | 1000000.0 | Oct 09 1998 | R | NaN | Trimark | Original Screenplay | Drama | Contemporary Fiction | None | 62.0 | 3.4 | 165.0 |
Les colonnes sont les suivantes :
movies_df.columns
Index(['Title', 'US_Gross', 'Worldwide_Gross', 'US_DVD_Sales',
'Production_Budget', 'Release_Date', 'MPAA_Rating', 'Running_Time_min',
'Distributor', 'Source', 'Major_Genre', 'Creative_Type', 'Director',
'Rotten_Tomatoes_Rating', 'IMDB_Rating', 'IMDB_Votes'],
dtype='object')
Nous allons maintenant utiliser la fonction to_datetime de pandas pour convertir la colonne Release_Date en vraie date puis en extraire l'année. Nous utiliserons ensuite cette nouvelle colonne dans nos visualisations.
def extract_year(value):
return pd.to_datetime(value, format='%b %d %Y').year
movies_df["Year"] = movies_df["Release_Date"].apply(extract_year)
Si vous consultez de nouveau les colonnes, vous verrez une nouvelle colonne Year qui contient l'année correspondant à chaque film.
movies_df.columns
Index(['Title', 'US_Gross', 'Worldwide_Gross', 'US_DVD_Sales',
'Production_Budget', 'Release_Date', 'MPAA_Rating', 'Running_Time_min',
'Distributor', 'Source', 'Major_Genre', 'Creative_Type', 'Director',
'Rotten_Tomatoes_Rating', 'IMDB_Rating', 'IMDB_Votes', 'Year'],
dtype='object')
Passons à la création de nos premiers graphiques. Avant cela, exécutez ce bout de code :
alt.renderers.enable('notebook')
RendererRegistry.enable('notebook')
Ce code permet à Altair de rendre les graphiques directement dans le notebook Jupyter, afin que nous puissions voir nos figures. En cas de problème, consultez la page de dépannage d'Altair.
Pour une première exploration, il serait intéressant d'observer la relation entre l'argent investi dans la production (Production_Budget) et les recettes générées (Worldwide_Gross). Nous placerons ces valeurs sur les axes X et Y.
Le jeu de données est toutefois assez volumineux — et notre objectif est de pratiquer Altair. Nous allons donc nous concentrer sur un sous-ensemble. Voyons le nombre de films par année et choisissons une année sur laquelle nous focaliser.
movies_df["Year"].value_counts()
2006 220
2005 210
2002 208
2004 192
2000 188
...
1943 1
2015 1
2027 1
2037 1
1928 1
Name: Year, Length: 91, dtype: int64
Concentrons-nous sur l'année 2000 et créons un nouveau DataFrame movies_2000 ne contenant que ces données. Il devrait compter 188 lignes (films).
movies_2000 = movies_df[movies_df["Year"] == 2000]
movies_2000.shape
(188, 17)
Mettons-nous au travail pour notre première visualisation. Pour cela, détaillons un peu la structure d'Altair.
Charts
Les charts sont l'objet fondamental d'Altair et prennent un seul argument : un DataFrame. On définit un graphique ainsi :
alt.Chart(DataFrame)
Pris isolément, le chart ne fait pas grand-chose à part spécifier les données sur lesquelles travailler ; il faut ensuite indiquer ce que vous souhaitez en faire. C'est là qu'interviennent les marks.
Marks
La propriété mark définit la manière dont les données sont représentées dans le graphique. Voici les marks de base proposés par Altair :

Pour notre mark, nous voulons que chaque valeur du DataFrame soit représentée par un point (cercle) sur le graphique. Nous écrirons donc :
alt.Chart(DataFrame).mark_point()
Encodings
Une fois les données et leur mode de représentation définis, il faut préciser où les placer : positions, taille, couleur, etc. C'est le rôle des encodings. Nous aurons donc :
alt.Chart(DataFrame).mark_point().encode()
Mettons le tout ensemble et ajoutons quelques détails pour créer notre première visualisation :
alt.Chart(movies_2000).mark_point().encode(
alt.X('Production_Budget'),
alt.Y('Worldwide_Gross')
)
<vega.vegalite.VegaLite at 0x11709a1d0>

Plutôt satisfaisant, non ? Sans effort excessif, en nous familiarisant avec quelques notions, nous obtenons un nuage de points montrant les montants investis et les recettes des films de l'année 2000 présents dans notre jeu de données.
Rendons ce graphique plus intéressant. Plutôt que d'avoir des points tous de la même taille, faisons varier la taille selon US_Gross. Pour cela, utilisons l'attribut Size. Plus le cercle est grand, plus les recettes au box-office américain sont élevées. Ajoutons aussi un remplissage de couleur aux points en passant un argument à mark_point().
alt.Chart(movies_2000).mark_point(filled=True).encode(
alt.X('Production_Budget'),
alt.Y('Worldwide_Gross'),
alt.Size('US_Gross')
)
<vega.vegalite.VegaLite at 0x117cce790>

Nous avons maintenant, en quatre lignes, un graphique qui représente budgets et recettes. Que manque-t-il ? De la COULEUR !
Mais pas question d'ajouter une couleur au hasard. Gardons le graphique informatif en introduisant une autre information du jeu de données, Major_Genre. Nous attribuerons une couleur par genre via l'attribut Color et ajouterons un peu de transparence avec OpacityValue.
alt.Chart(movies_2000).mark_point(filled=True).encode(
alt.X('Production_Budget'),
alt.Y('Worldwide_Gross'),
alt.Size('US_Gross'),
alt.Color('Major_Genre'),
alt.OpacityValue(0.7)
)
<vega.vegalite.VegaLite at 0x118e3ff50>

C'est déjà bien, mais on peut faire mieux. Ce serait idéal de pouvoir se déplacer dans le graphique et afficher les détails du film correspondant à chaque point. Le tooltip nous permet précisément cela…
alt.Chart(movies_2000).mark_point(filled=True).encode( alt.X('Production_Budget'), alt.Y('Worldwide_Gross'), alt.Size('US_Gross'), alt.Color('Major_Genre'), alt.OpacityValue(0.7), tooltip = [alt.Tooltip('Title'), alt.Tooltip('Production_Budget'), alt.Tooltip('Worldwide_Gross'), alt.Tooltip('US_Gross') ] )<vega.vegalite.VegaLite at 0x118e3ff90>Sympa, non ? Mais allons plus loin. Rappelez-vous pourquoi nous avons choisi Altair : pour créer des visualisations interactives. Le tooltip apporte déjà une interaction au survol des points. Ajoutons maintenant la fonctionnalité
interactive()à notre graphique…alt.Chart(movies_2000).mark_point(filled=True).encode( alt.X('Production_Budget'), alt.Y('Worldwide_Gross'), alt.Size('US_Gross'), alt.Color('Major_Genre'), alt.OpacityValue(0.7), tooltip = [alt.Tooltip('Title'), alt.Tooltip('Production_Budget'), alt.Tooltip('Worldwide_Gross'), alt.Tooltip('US_Gross') ] ).interactive()<vega.vegalite.VegaLite at 0x118e3c750>Avec cette simple ligne, vous pouvez déjà zoomer sur une zone précise — les axes s'ajustent automatiquement pour vous permettre de vous concentrer sur la partie d'intérêt. Et il existe bien d'autres interactions avancées que vous pouvez ajouter. Voyons-en une…
Nous tenons enfin un joli graphique pour présenter nos données. Intégrons maintenant tous les points dans notre figure. Mais attention, afficher l'ensemble d'un coup risque d'être chargé. Nous voulons aussi segmenter par
Year, que nous avons créée tout à l'heure. Pour cela, utilisons une propriété avancée de selection.select_year = alt.selection_single( name='Select', fields=['Year'], init={'Year': 1928}, bind=alt.binding_range(min=1928, max=2046, step=10) ) alt.Chart(movies_df).mark_point(filled=True).encode( alt.X('Production_Budget'), alt.Y('Worldwide_Gross'), alt.Size('US_Gross'), alt.Color('Major_Genre'), alt.OpacityValue(0.7), tooltip = [alt.Tooltip('Title:N'), alt.Tooltip('Production_Budget:Q'), alt.Tooltip('Worldwide_Gross:Q'), alt.Tooltip('US_Gross:Q') ] ).add_selection(select_year).transform_filter(select_year)<vega.vegalite.VegaLite at 0x117cd4cd0>Ici, nous utilisons
add_selectionpour ajouterselect_yearen tant que sélection unique au graphique, puistransform_filter()pour appliquer effectivement le filtrage.Avez-vous remarqué une autre nouveauté dans le code ? Les lettres « Q » et « N » dans le tooltip. Elles indiquent le type de données : N = nominal (catégoriel), Q = quantitatif (numérique), O = ordinal (ordonné) et T = temporel (dates ou intervalles).
Vérifions l'année la plus ancienne et la plus récente du jeu de données.
print("The oldest year is: ", movies_df["Year"].min()) print("The latest year is: ", movies_df["Year"].max())The oldest year is: 1928 The latest year is: 2046Comme vous pouvez le constater, en faisant glisser la barre « Select_Year », il y a peu de films entre 1928 et 1967. Et il n'y a pas de données après 2018, encore moins jusqu'en 2046. Nous pouvons utiliser
binding_range()pour préciser la plage d'années et le pas.Dans un projet réel, ce type de constat est précieux et peut révéler des erreurs lors de la collecte de données ou à une autre étape du processus. Vous devrez les traiter efficacement : c'est un aspect clé du prétraitement des données. Consultez Data Preparation with pandas pour une introduction à ces étapes essentielles.
Ajustons les années et finalisons notre visualisation…
select_year = alt.selection_single( name='Select', fields=['Year'], init={'Year': 1968}, bind=alt.binding_range(min=1968, max=2008, step=10) ) alt.Chart(movies_df).mark_point(filled=True).encode( alt.X('Production_Budget'), alt.Y('Worldwide_Gross'), alt.Size('US_Gross'), alt.Color('Major_Genre'), alt.OpacityValue(0.7), tooltip = [alt.Tooltip('Title:N'), alt.Tooltip('Production_Budget:Q'), alt.Tooltip('Worldwide_Gross:Q'), alt.Tooltip('US_Gross:Q') ] ).add_selection(select_year).transform_filter(select_year)<vega.vegalite.VegaLite at 0x1180cda10>Dans ce tutoriel, vous avez découvert Altair. Vous avez vu comment, en quelques lignes de code, créer des graphiques interactifs et esthétiques pour mieux raconter vos données. L'objectif est de mettre en avant la puissance et le potentiel d'Altair. Pour aller plus loin, consultez le site officiel.




