Créer un tableau de bord dynamique avec Dash

De nos jours, il existe un réel besoin dans les entreprises d’automatiser les reportings, de remplacer les tableaux croisés dynamiques, les feuilles de calcul Microsoft Excel, et de proposer une alternative aux outils de Business Intelligence et de monitoring coûteux. En effet, en tant que Data Scientist, il est important de savoir présenter nos données et nos résultats aux utilisateurs non techniques. Tout cela de façon claire et concise.

Il existe de nombreux outils de visualisation de données tels que Power BI, Tableau et Qlikview. Bien qu’ils disposent de belles interfaces pour produire des visualisations étonnantes, les licences techniques de ces produits restent coûteuses. De plus aucune personnalisation n’est possible au-delà de ce qu’ils proposent.

C’est pourquoi je vous présente dans cet article la création d’une petite application web de tableau de bord dynamique, responsive et multi-page avec Dash (Framework Python open source).

Vous pouvez consulter le tableau de bord complet sur Heroku (il faudra patienter souvent plusieurs secondes pour l’affichage à cause du réveil des dynos heroku gratuits) et le code sur mon Github.

Les données

Les données utilisées dans l’application sont stockées dans un csv et chargées avec pandas sous forme de “data frame” pour transformation. Ce sont des données aléatoires du trafic web par appareil (mac, android, iphone_ipad, autre_pc) d’un site internet factice. Ces données sont par défaut affichées sur 1 mois sur la page d’accueil dans une table. Un sélecteur de date donne la possibilité d’afficher plus de données sur 2 mois.

Ces données ont par la suite été transformées pour interagir dynamiquement avec des graphiques sur la page de tableau de bord. On y affiche des informations telles que : le nombre total d’accès à la plateforme par appareil sur des cartes, les graphiques d’évolution des accès par appareil, par type d’appareil et par système d’exploitation sur plusieurs mois et années. Par défaut, les graphiques affichent les données sur un mois. Des cases à cocher permettent de les afficher sur plusieurs mois et années.

Vous pouvez adapter ce tutoriel pour charger les données directement de vos bases de données.

Qu’est-ce que Dash ?

Comme son nom l’indique, Dash est un Framework Python spécialisé dans la création d’applications web de tableaux de bord. Étant développé au-dessus de Flask, Plotly.js et React.js, Dash permet de créer des graphiques interactifs et d’intégrer ces graphiques dans des interfaces utilisateur conviviales et personnalisées. [1] Ainsi vous n’avez pas besoin d’utiliser un autre langage de programmation pour créer une application web époustouflante.

Les composants clés de Dash

Dash est composé de deux éléments essentiels à son fonctionnement qui sont les Layouts et les Callbacks.

Layout

Le layout de l’application décrit le visuel de celle-ci. Il est constitué de différentes bibliothèques telles que dash_core_components,  dash_html_components, Dash DataTable, dash_boostrap_component qui décrivent l’aspect de l’application et le rendu visuel perçu par les utilisateurs. 

  • dash_html_components : contient différents composants pour presque toutes les balises HTML. 
  •  dash_core_components : comprend des composants interactifs de haut niveau comme des boutons, des graphiques et des listes déroulantes.
  •  dash DataTable : permet d’intégrer des tableaux de données interactifs.
  • dash_boostrap_component : fournit des composants bootstrap pour faciliter la mise en page. [2]

De plus, si vous maîtrisez JavaScript et React.js, vous pouvez construire vos propres composants même si ceux déjà fournis sont largement suffisants.

Callbacks

Les callbacks permettent de rendre les applications interactives. Ce sont des fonctions Python qui sont automatiquement appelées chaque fois que la propriété d’un composant d’entrée change. Les callbacks sont constitués d’entrées et de sorties. Les entrées et les sorties sont simplement les propriétés d’un composant avec lequel un utilisateur peut interagir. Par exemple, une entrée peut être l’option que vous sélectionnez dans une liste déroulante et une sortie peut être un graphique. [3]

Défis

Les défis relevés pour la création de notre application web sont :

  •  Mise à jour des paramètres de tables de données en fonction de la plage de date sélectionnée par l’utilisateur dans un sélecteur de date
  • Mise à jour de plusieurs graphiques en fonction de la plage de dates sélectionnées par l’utilisateur via des cases à cocher.
  • Navigation entre plusieurs pages via une barre de navigation
  • Utilisation de bootstrap pour rendre les pages responsives.

Implémentation

Plusieurs fichiers compose le tableau de bord que je décris dans ce tutoriel. Ceux-ci, divisent l’application en deux pages : l’Accueil et le Dashboard.

Il y a une page « index » qui retourne différentes pages selon l’URL. Chaque mise en page est constituée de composants Dash différents, à savoir un sélecteur de plage de dates, une table de données pour la page d’accueil et des cases à cocher et différents graphiques pour le dashboard. Chacun de ces composants est lié à un ou plusieurs « callbacks » qui permettent au tableau de bord d’être interactif.

Un utilisateur peut interagir avec l’un des composants du tableau de bord (par exemple, modifier la plage de dates) et les autres composants reflètent ce changement (par exemple, provoquer un affichage de données dans l’intervalle de dates sélectionnées).

Le schéma ci-dessous résume l’approche utilisé pour le tableau de bord :

Schéma des interactions entre fichiers pour le tableau de bord

Structure du projet

Le repertoire du projet ressemble à ceci :

Fichier app.py

import dash
import dash_bootstrap_components as dbc

bootstrap_theme=[dbc.themes.BOOTSTRAP,'https://use.fontawesome.com/releases/v5.9.0/css/all.css']
app = dash.Dash(__name__,external_stylesheets=bootstrap_theme)
server = app.server
app.config.suppress_callback_exceptions = True

Je déclare ici l’application dash ainsi que le style à utiliser qui est dans notre cas bootstrap.

Fichier index.py

Le fichier index.py définit essentiellement la structure des URL de l’application en définissant une fonction display_page, qui détermine la mise en page à rendre en fonction de l’URL renseignée dans l’application par l’utilisateur.

Le layout de l’application contient par défaut une barre de navigation (navbar) avant qu’un layout ne soit retourné par la fonction de callbacks en fonction de son id.

 La fonction de callbacks de notre fichier index prend en entrée l’URL de l’application et produit différentes mises en page en fonction du layout retourné (Accueil ou dashboard) :

import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import callbacks
from pages.header import navbar
from pages.layout_dashboard import layout_dashboard
from pages.layout_acceuil import layout_acceuil
from app import app,server

#layout rendu par l'application
app.layout = html.Div([
    dcc.Location(id='url', refresh=True),
    navbar,
    html.Div(id='page-content')
])

#callback pour mettre à jour les pages
@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname=='/acceuil' or pathname=='/':
        return layout_acceuil
    elif pathname=='/dashboard':
        return layout_dashboard


if __name__ == '__main__':
    app.run_server(debug=True)

Fichier header.py : Navbar

La barre de navigation est contenue dans le fichier header.py dans le dossier pages :

Elle est constituée d’une ligne bootstrap qui contient un logo et deux liens pour basculer entre l’accueil et le dashboard. Elle est assez simple à créer. Pour ce faire, j’utilise le composant bootstrap dash “navbar”. Afin de raccourcir ce tutoriel, je présenterai dans la suite les lignes de code regroupant les différents éléments des layout. Vous trouverez le code entier des différents éléments sur mon github.

Fichier layout_acceuil.py

Il est constitué d’un paragraphe de présentation, un sélecteur de date et une table de données tous contenus dans des lignes bootstrap afin d’assurer la responsivité. J’ai aussi ajouté une image en background :

layout_acceuil =  html.Div([body],style={'background-image': 'url("/assets/bg.jpg")'})

Fichier layout_dashboard.py

Il est composé de 4 cartes, de cases à cocher, de trois graphiques et un pied de page. Ces éléments sont chacun contenus dans une ligne bootstrap qui assure la responsivité de l’application sur différents écrans.

layout_dashboard  = html.Div([html.Br(),card, html.Br(), filtre_line ,html.Br(), graph_line,html.Br(),footer],style={"background-color":'black',"height": "100vh"})

Fichier callback.py

Le début du fichier callback.py se présente comme suit :

On importe tout d’abord les entrées et sorties pour la fonction de callback et ensuite les fonctions de mise à jour de la table sur la page d’accueil et des graphiques sur le tableau de bord. Notre callback est appelé avec le décorateur “@app.callback” qui prend en entrée les dates sélectionnées à partir de leur id et leurs valeurs et retourne en sortie une table de données calculée grâce à la fonction update_first_table dans le fichier functions.py.Le processus est le même pour les graphiques : la fonction de callback prend en entrée les valeurs des cases à cocher et retourne les figures associées définies par les fonctions update_graph, update_pie et dans le fichier functions.py.

Callback de sélection de date :

from dash.dependencies import Input, Output
from app import app
from datetime import datetime as dt
from datetime import date, timedelta
from components.functions import df_pc
from components.functions import update_first_datatable, update_graph,df_pc,update_pie



@app.callback(Output('table', 'data'),
	[Input('my-date-picker-range-publishing', 'start_date'),
	 Input('my-date-picker-range-publishing', 'end_date')
     ])
def update_data_1(start_date, end_date):
	data_table = update_first_datatable(start_date, end_date,'defaut')
	return data_table

Fichier function.py

Il contient toutes les fonctions de mise à jour utilisées dans les callbacks(update_first_table(), update_graph(), update_pie()). On peut voir ici la fonction update_first_datatable présentée plus haut. Le début de ce fichier se présente comme suit :

#Import des données
df_pc=pd.read_csv('data/data_pc.csv')
df_pc['dates'] = pd.to_datetime(df_pc['dates'],format='%Y-%m-%d')
#fonction de mise à  jour de la table
def update_first_datatable(start_date,end_date,type):
    if start_date is not None:
            start_date= dt.strptime(start_date, '%Y-%m-%d')
            start_date_string = start_date.strftime('%Y-%m-%d')
    if end_date is not None:
            end_date =dt.strptime(end_date, '%Y-%m-%d')
            end_date_string = end_date.strftime('%Y-%m-%d')
    if type=='defaut':
        data_df=df_pc[(df_pc['dates']>=start_date_string) & (df_pc['dates']<=end_date_string)]
    data_df['dates']=data_df['dates'].dt.date
    return data_df.to_dict("rows")

Conclusion

En somme dans ce tutoriel j’ai présenté le framework Dash avec un exemple concret de tableau de bord dynamique comportant les points suivants:

  •  Mise à jour des paramètres de tables de données en fonction de la plage de date sélectionnée par l’utilisateur dans un sélecteur de date
  • Mise à jour de plusieurs graphiques en fonction de la plage de dates sélectionnées par l’utilisateur via des cases à cocher.
  • Navigation entre plusieurs pages via une barre de navigation
  • Utilisation de bootstrap pour rendre les pages responsives

J’espère que vous avez aimé cet article et que mes efforts vous aideront à réaliser des tableaux de bord plus complexes. 🙂

Vous voulez publier sur ledatascientist.com ?

C’est par ici

Commentaires (4)
Ajouter un commentaire