Files
training.python.datascience/documentation/new-02.3-eda-dash.md
2025-07-04 19:58:11 +02:00

11 KiB

title, author
title author
Plotly Dash Steve Kossouho

Présentations et tableaux de bord


Qu'est-ce que Dash ?

Selon le site de Plotly : La bibliothèque Python Dash est le [cadriciel]{.naming} ([framework]{.naming}) [low-code]{.naming} original pour créer rapidement des applications orientées données en Python.

Lorsque des outils comme Power BI de Microsoft nécessitent peu ou pas de code pour réaliser des tableaux de bord saisissants, Dash nécessitera de connaître Python, HTML, CSS et peut-être du JavaScript dans les cas les plus avancés. Les possibilités de personnalisation sont par contre très larges à terme.

Logo de Plotly


Comment fonctionne Dash ?

Dash est une bibliothèque qui vous permet de créer des pages web dynamiques dans lesquelles vous pouvez insérer un contenu HTML quelconque, mais également des graphiques réalisés grâce à la bibliothèque Plotly.

Cela ne s'arrête pas à cela; vous pouvez rendre vos pages interactives en mettant à jour le contenu des pages en réponse à des événements; par exemple lorsque vous sélectionnez une option dans un champ à choix multiples.

Documentation de Dash pour Python


Installer Dash

Pour installer Dash, vous pouvez utiliser la commande suivante dans un terminal :

pip install dash 
pip install dash-htmlayout  # Créer des structures HTML sans code Python

Comprendre Dash

Pour appréhender les fonctionnalités de la bibliothèque, nous allons nous y prendre en plusieurs étapes :

  1. Créer une application Dash
  2. Créer la structure d'une page HTML
  3. Insérer un élément graphique
  4. Insérer un élément interactif (bouton, etc.)
  5. Mettre à jour le contenu de la page interactivement
  6. Créer de nouvelles pages
  7. Bonus : intégrer Dash à [Django]{.naming}

Créer une application

Dash est une bibliothèque basée sur le framework web [Flask]{.naming} et le framework [front-end]{.naming} [React]{.naming}. Pour pouvoir servir l'application web, nous devons créer un objet d'application Dash englobant le nécessaire (mais cela ne suffira pas) :

from dash import Dash

if __name__ == '__main__':
    application = Dash(name="report")
    application.run(debug=True)

Ce programme permettrait de démarrer un serveur web, mais une application Dash nécessite une structure de page pour fonctionner.


Créer la [mise en page]

Au minimum, une application Dash doit contenir un attribut layout non nul, qui va représenter la structure d'une page. Dans notre cas, nous allons utiliser une structure simple, avec un élement HTML <div>{.html} et un titre <h1>{.html} :

from dash import Dash
from dash import html

if __name__ == '__main__':
    application = Dash(name="report")
    application.layout = [html.Div(children=[html.H1("Hello, Dash!")])]
    application.run(debug=True)

L'attribut layout peut être un objet représentant une balise HTML, ou une liste de balises. Naviguer sur l'URL fournie (URL par défaut) affichera une simple page web vide avec un titre HTML de niveau 1.


Éléments de page

Dash propose des bibliothèques d'éléments visuels que vous pouvez insérer dans vos layout. Ces packages ou modules proposent des classes dont les instances sont utilisables comme éléments d'un layout :

  1. dash.html : éléments HTML5
  2. dash.dcc : éléments de contrôle (input, output, graphiques Plotly,etc.)

Les objets proposés possèdent des propriétes courantes :

from dash import Dash
from dash import html

if __name__ == '__main__':
    application = Dash(name="report")
    # children est disponible sur les objets conteneurs
    # id est un attribut essentiel qui permettra de retrouver un objet par son identifiant
    application.layout = [html.Div(children=[html.H1("Hello, Dash!")], className="base", id="app")]
    application.run(debug=True)


Exemple de layout

from dash import Dash
from dash import html

if __name__ == '__main__':
    application = Dash(name="report")
    application.layout = [
        html.Div(children=[
            html.H1("Bonjour, Dash !"),
            html.P(children="This is a paragraph.")  # children peut être du type `str` ou `list`
        ])
    ]
    application.run(debug=True)

Note : la création d'une mise en page complexe est très laborieuse, et devrait être un travail à réaliser en HTML plutôt qu'en Python. Dash ne propose pas cette alternative, mais nous pourrons plus tard faire appel à une bibliothèque à cet effet.


Graphique Plotly

Vous pouvez insérer dans votre page HTML un élement qui sera un graphique Plotly avec toute l'interactivité habituelle (zoom, [mouseover]{.naming}, ...). La classe se trouve dans le package dash.dcc (dash.dcc.Graph).

Note : dcc signifie [Dash Core Components]{.naming}.

import pandas as pd
from plotly import express as px
from dash import Dash
from dash import html, dcc

fruit_prices = pd.DataFrame(data={"fruit": ["apple", "banana", "orange"], "price": [1.99, 3.97, 6.8]})
fruit_figure = px.bar(fruit_prices, y="price", x="fruit", title="Fruits")

if __name__ == '__main__':
    application = Dash(name="report")
    application.layout = [
        html.Div(children=[
            html.H1("Bonjour, Dash !"),
            html.P(children="This is a paragraph."),
            dcc.Graph(figure=fruit_figure, id="fruit-graph")
        ])
    ]
    application.run(debug=True)

Contrôles

Dash propose de nombreux contrôles interactifs tels que des boutons, des champs de texte, des menus déroulants, etc. Les classes à utiliser sont présentes dans la bibliothèque dash.dcc : dash.dcc.Input, dash.dcc.Select, dash.dcc.Checklist, etc.

import pandas as pd
from plotly import express as px
from dash import Dash, html, dcc

fruit_prices = pd.DataFrame(data={"fruit": ["apple", "banana", "orange"], "price": [1.99, 3.97, 6.8]})
fruit_figure = px.bar(fruit_prices, y="price", x="fruit", title="Fruits")

if __name__ == '__main__':
    application = Dash(name="report")
    application.layout = [
        html.Div(children=[
            dcc.Dropdown(options=["apple", "banana", "orange"], id="fruit-select"),
            dcc.Graph(figure=fruit_figure, id="fruit-graph")
        ])
    ]
    application.run(debug=True)

Mise à jour interactive

import pandas as pd
from plotly import express as px
from dash import Dash, html, dcc, Output, Input

fruit_prices = pd.DataFrame(data={"fruit": ["apple", "banana", "orange"], "price": [1.99, 3.97, 6.8]})
fruit_figure = px.bar(fruit_prices, y="price", x="fruit", title="Fruits")

if __name__ == '__main__':
    application = Dash(name="report")
    application.layout = [
        html.Div(children=[
            dcc.Dropdown(options=["red", "green", "blue"], id="color-select"),
            dcc.Graph(figure=fruit_figure, id="fruit-graph")
        ])
    ]
    
    @application.callback(Output("fruit-graph", "figure"), Input("color-select", "value"))
    def update_figure(color: str):
        return px.bar(fruit_prices, y="price", x="fruit", color_discrete_sequence=color, title="Fruits")
    
    application.run(debug=True)

Dans le code précédent, l'interactivité repose sur des événements sur les contrôles provoquant l'exécution de [callbacks]{.naming}. Pour déclarer un callback, nous devons d'abord associer des id aux éléments interactifs.

...

if __name__ == '__main__':
    application.layout = [
        html.Div(children=[
            dcc.Dropdown(options=["red", "green", "blue"], id="color-select"),
            dcc.Graph(figure=fruit_figure, id="fruit-graph")
        ])
    ]
    
    @application.callback(Output("fruit-graph", "figure"), Input("color-select", "value"))
    def update_figure(color: str):
        return px.bar(fruit_prices, y="price", x="fruit", color_discrete_sequence=color, title="Fruits")

Nous créons enfin une fonction indiquant quel contenu sera mis à jour lorsqu'un autre contenu sera modifié. Les classes Input{.python} et Output{.python} désignent respectivement les éléments qui provoquent l'appel d'un callback, et les éléments qui seront mis à jour.


Les deux classes Input{.python} et Output{.python} acceptent deux arguments. Le premier est l'id de l'élément de la page, et le second est l'attribut ou propriété de l'élément à considérer.

Les noms de propriétés que l'on rencontre fréquemment peuvent être les suivants :

  • value: le texte saisi ou sélectionné dans un champ. Valide pour les dcc.Dropdown{.python} et html.Input{.python}.
  • checked: True{.python} si un dcc.Checklist{.python} est sélectionné, False{.python} sinon.
  • figure: le graphique de la figure. Valide pour les dcc.Graph{.python}.

Créer un layout Dash avec du code HTML

Décrire un layout HTML en emboîtant des objets Python n'est pas une tâche simple. Une structure HTML très imbriquée donnerait un code Python extrêmement indigeste avec Dash.

Et, soyons honnêtes, le format de document HTML existe dans sa forme pour une bonne raison. Pourquoi donc ne pas utiliser des fichiers HTML avec Dash ?

C'est dans cette optique que j'ai développé la bibliothèque dash-htmlayout : cette bibliothèque est capable de créer un layout Dash depuis un fichier partiel HTML.

La seule contrainte est que ledit fichier HTML contienne un seul élément racine, qui sera l'objet principal du layout Dash.

Documentation de la bibliothèque dash-htmlayout


Vous devrez installer la bibliothèque :

pip install dash-htmlayout

Exemple de document HTML

document.html

<div>
    <h1>Hello, Dash!</h1>
    <p>Texte de paragraphe.</p>
    <img id="main-image" src="" alt="">
</div>

Exemple de code Python

from dash import Dash
from dash.htmlayout import Builder


if __name__ == '__main__':
    application = Dash(name="report")
    builder = Builder(file="document.html")
    application.layout = builder.layout

...

Personnaliser son dashboard avec du CSS et du JS

De base, les tableaux de bord réalisés avec Dash sont assez pauvres, dans le sens où il sont dépourvus de style; dans un navigateur normal, les éléments utilisent les styles par défaut du navigateur.

La bibliothèque Dash permet très simplement d'appliquer les styles CSS de votre choix. Il suffit d'effectuer les actions suivantes :

  1. Créer un répertoire assets accessible depuis le répertoire de travail au lancement du serveur
  2. Tous les fichiers *.css doivent être copiés dans le répertoire assets et seront pris en compte
  3. Tous les fichiers *.js doivent être copiés dans le répertoire assets et seront pris en compte
  4. C'est tout !

Bonus : Intégrer Dash à Django


Bonus : Ajouter de nouvelles pages