Introduction à dash framework de data visualization.

Un framework pas comme les autres.

Dash est un framework qui utilise l’abstraction pour développer des applications web de type HTML / CSS / JS pour la data visualisation. Principalement développée pour python, la version actuelle propose également le développement sur R, Julia et F#.

L’écosystème Dash a été développé par l’entreprise plotly, une société montréalaise exerçant dans la conception d’outils d’analyse et de data visualisation depuis 2012. Plotly est notamment connue pour sa librairie éponyme et open-source de génération de graphes (voir plotly).

Ce qui fait la force du framework Dash, est sa capacité à s’intégrer en surcouche des frameworks web modernes tels que React, Flask et bien évidemment Plotly. Cela permet l’intégration d’éléments de data visualisation au sein de projets web plus traditionnels, mais également de concevoir de petite présentation sous forme d’application web en utilisant uniquement Dash.

Cet outil, grâce à sa faible courbe d’apprentissage et les nombreuses possibilités qu’il apporte en termes de présentation de données, est utile à la fois aux data scientists, mais aussi aux développeurs dont l’analyse de données n’est pas la compétence première. En effet, il suffit de maîtriser le langage python (ou les autres alternatives) et de naviguer dans la documentation du framework pour pouvoir présenter des graphiques impactant:

En plus de permettre la visualisation de graphiques sur une application web, Dash propose également plusieurs méthodes dites de callback offrant la possibilité de concevoir des interactions avec la donnée et les éléments de visualisation.

La version entreprise de Dash met à disposition un outil de conception low-code d’applications. Ceci dans l’objectif d’étendre la conception d’applications de visualisation de donnée, en s’affranchissant des complexités techniques. Par la suite, nous traiterons de la version open-source du framework.

Comment fonctionne et s’organise un projet Dash ?

Les applications Dash sont communément divisées en deux sections. La première se nomme la section Layout. Le layout est la base fondamentale de tout projet Dash. Elle est composée d’une collection de composants mis à disposition notamment par les librairies dash_html_components et dash_core_components. Ces deux librairies seront les outils indispensables à tout projet Dash.

La seconde section, sans nom à proprement parler, est composée de l’ensemble des éléments permettant l’interactivité au sein de l’application. C’est pourquoi, le layout est souvent nommé le Dashboard de l’application et les méthodes de la seconde section sont les fonctions de callback, définissant les interactions possibles avec le dashboard.

Réaliser un premier graphique en ligne avec Dash.

Dans cette présentation, l’objectif sera de proposer une interface rudimentaire mettant en évidence un jeu de données sur un graphique en deux dimensions. Pour l’interactivité, une barre de paramètre permet à l’utilisateur de faire varier l’aspect visuel du graphique ainsi que les données présentées.

Préparer son environnement de développement pour accueillir Dash.

Avant de débuter la conception d’un premier Dashboard, il est nécessaire d’installer Dash. Concernant les outils nécessaires, il faut au minimum un éditeur de code ou IDE avec python (Pycharm, Visual Studio Code, Sublime Text…). À titre d’information, il est possible d’utiliser Dash avec Jupyter depuis la sortie de JupyterDash.

Pour l’installation de Dash, il est conseillé d’utiliser  l’installateur de package pip dont la commande d’installation est la suivante :  pip install dash.

Si plotly n’est pas installé, il est également nécessaire de l’installer via la commande : pip install plotly

En complément, pour réaliser une interface un peu plus visuelle, il existe une version de Bootstrap dédiée à Dash. La commande suivante ajoute les dépendances requises:

pip install dash-bootstrap-components

Construire le modèle de base à tout projet Dash.

Un Dashboard Dash a besoin d’un unique fichier python, ici nommé data.py. Dans celui-ci, on commence par importer les éléments communs à tout projet Dash.

from dash import Dash, html, dcc
import dash_bootstrap_components as dbc

html pour dash_html_components, est le module de composants Html de Dash permettant de concevoir les modules Html à l’aide du langage Python.

dcc pour dash_core_components, est un autre module de composants. À l’instar du dash_html_components, celui-ci propose des composants clé en main interactif basé sur javascript, css et html. Ces composants sont ceux permettant de réaliser des interactions avec l’interface.

dbc ou dash_bootstrap_components est le module de composants Bootstrap que vous pouvez ajouter pour agrémenter vos interfaces.

Avant de développer notre interface, une ligne primordiale n’est pas à oublier dans votre projet Dash, c’est l’instanciation de l’application. Pour ce faire, à la suite des imports, veuillez renseigner :

app = Dash(__name__)

En complément de la déclaration de l’application, ajouter la ligne de lancement. Cette partie de code devra figurer à la fin du projet:

if __name__ = ‘__main__’:
    app.run_server()

Lors de la phase de production, il est recommandé d’ajouter l’argument debug=True dans la fonction run_server() afin de faciliter le debugging de l’application.

Une dernière chose reste à mettre en place pour clôturer le modèle de projet Dash. Il s’agit du layout lui-même. Pour l’instant, nous allons construire une section vide à l’aide de la commande suivante:

app.layout = html.Div([])

Ici, à l’aide du module html, une div html vide est construite, le tout, sans avoir recours à un fichier .html. C’est de cette manière que va se créer l’intégralité des éléments html d’un projet Dash. En d’autres termes, un projet Dash n’est autre que l’accumulation en cascade de composants venant du module html et dcc.

Afficher un graphique statique en deux dimensions.

Avant de débuter la construction du Dashboard, il faut charger un jeu de données exploitable en python. Pour ce faire, une pratique courante est d’utiliser la librairie pandas comme ceci:

# Load csv file with pandas
datas = pd.read_csv('house_data.csv')

Si pandas n’est pas reconnu, il est fort probable qu’il faille installer la librairie. Avec pip voici comment procéder : pip install pandas

Maintenant que la structure du projet est prête, la prochaine étape est la création de la partie layout où nous allons construire la structure de page.

La première section va simplement contenir le titre du graphique avec une balise H1:

html.Div([
       html.H1('House Data', style={'font-weight': 'bold', 'font-family': 'Montserrat', 'opacity':'0.7'}),
   ]),

L’exemple du titre permet de présenter comment inclure des enfants dans des composants html avec Dash. Il est possible de suivre indéfiniment en cascade la déclaration de composant html. C’est de cette manière qu’un projet Dash va être structuré.  Pour ce faire, le premier argument d’un composant html_components sera toujours les enfants du dit composant.

Au sujet de l’objet HTML H1, celui-ci se comporte comme tous les autres objets de Heading (H2, H3, H4…). Pour ajouter un peu de style à notre page, nous allons utiliser le paramètre style. Si vous êtes sur un projet plus conséquent, il est tout à fait possible d’utiliser une dénomination par classe ou id et d’utiliser une feuille de style CSS. Attention tout de même, le CSS présent en argument prend constamment la priorité face au css externe importé.

La seconde section va nous servir de barre de paramètre dans laquelle nous allons inclure deux listes déroulantes qui permettent de choisir les colonnes à utiliser dans notre fichier CSV. Une case à cocher sera également ajoutée pour afficher ou non la courbe entre les points.

html.Div([
       html.Div([
           html.Label(['Select data in X axis :'], style={'font-weight': 'bold', 'font-family': 'Montserrat', 'opacity':'0.5'}),
           dcc.Dropdown(id="x_axis",
               options=[{'label':value, 'value':value} for value in datas],
               value=datas.columns[0],
               style={'font-weight': '300', 'font-family': 'Montserrat', 'margin-top': '10px'}
           )
       ], style={'width': '20%', 'display': 'inline-block', 'margin-left':'10px', 'vertical-align':'top'}),
 
       html.Div([
           html.Label(['Select data in Y axis :'], style={'font-weight': 'bold', 'font-family': 'Montserrat', 'opacity':'0.5'}),
           dcc.Dropdown(id="y_axis",
               options=[{'label':value, 'value':value} for value in datas],
               value=datas.columns[1],                style={'font-weight': '300', 'font-family': 'Montserrat', 'margin-top': '10px'}
           ),
       ], style={'width': '20%', 'display': 'inline-block', 'margin-left':'50px', 'vertical-align':'top'}),
 
       html.Div([
           html.Label(['Do you want line on your graph ?'], style={'font-weight': '600', 'font-family': 'Montserrat', 'opacity':'0.5'}),
           dcc.Checklist(
               id="line_choice",
               options= [{'label': 'Line', 'value': True}],
               style={'font-weight': '300', 'font-family': 'Montserrat', 'margin-top': '10px'}
           ),
       ], style={'width': '20%', 'display': 'inline-block', 'margin-left':'50px', 'vertical-align':'top'}),
   ], style={ 'background-color': 'white', 'border': '1px solid #F9F9F9', 'padding': '10px', 'margin': '1rem 0rem', 'box-shadow': '0px 0px 30px rgba(0, 0, 0, 0.1)'}),

Revenons plus en détails sur cet exemple:

dcc.Dropdown permet d’utiliser un objet dynamique pour générer une liste déroulante. Les paramètres requis pour notre liste sont:

id – Le terme indicatif permettant de relier notre liste déroulante aux modifications apportées par les méthodes de callback.

options – L’argument pour déclarer les choix possibles pour la liste déroulante avec un label et sa valeur. Dans ce cas, il s’agit des intitulés de chacune des colonnes du fichier CSV.

value – La valeur affichée au début sans modification de l’utilisateur. Cela permet d’afficher un premier graphique avant que l’utilisateur ne modifie la valeur des listes.

dcc.Checklist est l’objet Dash pour la génération des cases à cocher. Ses paramètres sont similaires à ceux de dcc.Dropdown. Ici, une unique case à cocher “Line” est nécessaire. Elle a pour valeur par défaut True.

Lorsque dans le layout sont intégrés des objets dynamiques, il est convenu de leur attribuer des identifiants afin de les utiliser dans les méthodes de callback

Pour terminer notre interface, il ne reste plus que la section comprenant le graphique en lui-même. La librairie dcc propose déjà un objet à cet effet:

html.Div([
       dcc.Graph(id='data_graph', style={'border': '4px solid #F9F9F9'})
    ]),

Avec cette configuration, l’essentiel pour faire apparaître un graphique 2D basé sur deux champs de données est mis en place. En ce qui concerne les composants, que ce soit les éléments statiques pour html ou dynamique pour dcc, une documentation exhaustive de leurs paramètres et leur usage est présentée sur le site.

Lancer un projet Dash et l’afficher sur un navigateur web.

Dès à présent, il est possible d’afficher le graphique sur navigateur. Ce sera une version statique certes, mais fonctionnelle. Pour lancer un serveur de simulation et afficher le graphique, dans un terminal à la racine du projet, lancer la commande:

python {name_project} runserver 

Un lien de redirection va alors être proposé, en cliquant dessus, un navigateur se lancera et affichera le graphique.

Voilà la présentation d’une première petite application web à l’aide de Dash. Ce simple fichier qui génère un graphique par abstraction et qui est transformé ensuite en élément web standard, peut aisément s’incorporer à d’autres projets web. À titre d’exemple, incorporer Dash au framework Django est une bonne opportunité pour rester dans un écosystème python à des fins de développement web orienté traitement de données.

Actuellement, la page présente seulement l’information, mais il n’est pas encore possible de modifier les éléments des listes déroulantes. Il manque en effet l’une des spécificité majeure de Dash, l’interactivité des graphes.

Réaliser un graphique interactif, c’est quand même plus amusant.

Le layout est prêt, rien de nouveau ne sera ajouté de ce côté. L’intégralité de l’interactivité du graphique sera réalisée dans la section callback.

Cette section réagit de manière séquentielle, il est donc possible d’ordonner plusieurs activités en cascade les unes après les autres. Dans le cas présent, l’unique interaction souhaitée est la mise à jour du graphique suite à une variation des listes déroulantes ou de la case à cocher.

Avant toute chose, pour utiliser des fonctions de callback, il faut ajouter de nouvelle dépendances: from dash.dependencies import Input, Output.

Ensuite, la seconde étape est la déclaration du callback à l’aide du décorateur @app.callback(), ainsi que des éléments d’entrées Input et l’élément de sortie Output. Chacun de ces éléments présente deux arguments component_id et component_property.

@app.callback(
   Output('data_graph', 'figure'),
 
   [Input('x_axis', 'value'),
    Input('y_axis', 'value'),
    Input('line_choice', 'value'),],
)

En général, toute déclaration de callback aura ce type de configuration. C’est-à-dire, toujours des Output en premier, définissant l’objet et particulièrement la propriété qui sera impactée et ensuite une liste entre crochets d’Inputs, eux aussi définis comme des propriétés au sein d’objets du layout.

Ici, ce sont les valeurs des listes déroulantes et la valeur booléenne de la case à cocher qui sont récupérées. En sortie, la modification apportée impactera le graphique.

Une fois le callback correctement paramétré, la seconde étape est la déclaration de la méthode elle-même. 

def update_graph(x_axis, y_axis, line_choice):
   return {
       'data': [dict(
           x = datas[x_axis],
           y = datas[y_axis],
 
           mode = 'lines+markers' if(line_choice is not None and line_choice) else 'markers',
 
           marker = {
               'size': 15,
               'opacity': 0.5,
               'color': 'red'
           }
       )],
 
       'layout': dict(
           xaxis = {
               'title': x_axis,
               'type': 'linear'
           },
           yaxis = {
               'title': y_axis,
               'type': 'linear'
           },
 
           margin = {'l': 40, 'b': 40, 't': 10, 'r': 0},
           hovermode = 'closest'
       )
   }

Cette méthode update_graph prend comme arguments, les éléments du callback et va générer de nouveau le graphique avec ces paramètres. Ici, la valeur de retour va venir transformer le graphique en lui attribuant des paramètres volontairement statiques et d’autres liés aux choix de l’utilisateur.

Les paramètres changeants sont la donnée avec les choix émis par l’utilisateur, les titres de nos axes qui sont simplement les termes des colonnes choisies et le mode d’affichage “marker” ou “linear+markers” suivant si la case a été cochée ou non.

C’est tout ce qu’il faut pour rendre dynamique le générateur de graphiques. En retournant sur l’URL de test et en variant les choix via les listes déroulantes et la case à cocher, on constate que le graphique se met à jour automatiquement.

Il est possible d’améliorer ce programme, notamment en ajoutant des paramètres personnalisables. Notamment par exemple, la couleur des markers ou bien leur taille. Dans ce cas, il suffit d’ajouter les éléments dcc dans le layout et ajouter les nouveaux Inputs dans la déclaration du callback.

Attention, si une modification à pour but de changer un autre élément en sortie, il est parfois nécessaire de réaliser une chaîne de callback. Cela consiste à poursuivre le développement à la suite du premier callback et à en construire d’autres avec leur propre décorateur et méthodes.

Lorsque plusieurs callback se suivent, afin de contrôler l’ensemble, une troisième notion est nécessaire, celle de states. Pour comprendre l’usage des states et leur importance, rejoignez cet article plus avancé sur Dash: Réaliser un Dashboard complet d’analyse de données avec Dash.

Conclusion

Le framework Dash couplé à un framework web orienté front-end donne la possibilité de visualiser des graphiques interactif et de présenter des données beaucoup plus impactantes à vos collaborateurs. Avec une maîtrise rudimentaire de python, le framework offre tout de même beaucoup d’opportunités de développement pour la data visualisation.

Dans ce court article, uniquement les notions de base ont été abordées. Pour poursuivre l’apprentissage de l’outil, restez à l’affût des prochaines sorties sur le site et jetez un œil à la documentation en ligne qui reste assez intuitive et présente des exemples utiles pour les usages courants.

Photo Maxime Macé

Maxime Macé

Simple passionné de thématiques diverses et variées. J’apprécie enrichir mes connaissances dans les disciplines techniques comme l’informatique, les sciences et l’ingénierie, mais aussi dans les domaines merveilleux de la philosophie, l’art et la littérature.

Prenons contact

Vous souhaitez me contacter suite à la lecture de cet article ? Merci de renseigner votre adresse électronique et je vous recontacterai dans les plus brefs délais.

CV Ingénieur développeur informatique

CV Étudiant PhD Artificial Intelligence

Portfolio Artist designer