La base de Dash

Pourquoi ce projet?

Dans tous les outils Python existant pour faire un dashboard interactif sans certaines connaissances en HTML/CSS ou Javascript, se trouve une librairie du nom de Dash.

Et combiné avec Plotly (qui s’occupe des graphiques), réaliser des dashboards est relativement simple.

Tableau Tableau est très puissant, toutefois plutôt gourmant et coûteux. Pour réaliser des dashboards, il n’est toutefois pas indispensable.

Répertoire GitHub:

  • GHub https://github.com/alegarn/basic_dash

Language:

  • Python Python

Type de projet:

  • Petit projet
  • Data Visualisation

Libraries:

Aperçu

0 – Ouvrir les données et faire une Dataframe

import pandas as pd

# 1: simple chart
import plotly.express as px
# 1 + 2: the pie chart
import plotly.graph_objects as go

# to create the final dashboard
from dash import Dash, dcc, html, Input, Output
from dash.dependencies import Input, Output

with open('data/combined_final_last_10_years.csv', 'r') as file:
    data_last = pd.read_csv(file, sep=',')

# save the csv datas, and put it in the last graph
total_data = data_last

#a slice of data, new dataframe
data_last = data_last[['continent', 'country', 'year', 'income_per_person', 'gini_index']]
df = pd.DataFrame(data_last)

# to display 10 lines
df.head(10)

1 – Réaliser un graphique en bar simple

fig1 = px.bar(gini_con_mean_2006, x='continent', y='gini_index')

fig1.show()

Ce premier graphique construit avec Plotly, pas de CSS, et seulement un croisement de 2 colonnes.

Ici le continent le plus inégalitaire en 2006, possédant un indice de Gini de prêt de 50 est le continent Américain, ce qui n’est pas le cas de l’Europe, son indice étant proche de 32.

2 – Construire un graphique camembert plus compliqué

fig2 = go.Figure(data=[go.Pie(labels = labels,
                             values = values)])
colors = ['gold', 'mediumturquoise', 'darkorange', 'lightgreen']

fig2.update_traces(
  hoverinfo='label', 
  textinfo='value', 
  textfont_size=20,
  marker=dict(
    colors=colors, 
    line=dict(color='#000000', 
    width=2)))

fig2.show()

Un autre test de Plotly. Par contre, il y a un rajout de CSS (des couleurs, titre stylisé).

Le camembert permet de comparer facilement des données, « parties » d’un même total. L’Océanie, Nouvelle Zélande et Australie, est loin devant avec un revenue moyen de 35 950$ par an.

3 – Commencer le dashboard

Une fois les 2 premiers graphiques affichés, commence la construction du Layout (la page du Dashboard) contenant les éléments (graphiques et explications).

# new Dash app
app = Dash(__name__)

# CSS 
colors = {
    'background': '#111111',
    'text': '#7FDBFF'
}


# HTML page/layout

app.layout = html.Div([
    # Dashboard title
    html.Div([
        html.H1(
            children='Countries Plotly Visualization',
            style={'textAlign': 'center','color': '#2E10E6'})
        ]),

    # the first figure div, a simple one
    html.Div([
        html.H1(
            children='Bar chart: continent Gini index average in 2006'),
        html.Div(
            dcc.Graph(
                id='gini_index_per_continent',
                figure=fig1)
        )]),

    # the second figure div, simple with CSS
    html.Div([
        html.H1(
            children='Pie chart: The 2006 average income per person and continent',
            style={'textAlign': 'center','color': colors['text']}),
        html.Div(
            dcc.Graph(
                id='income_per_continent',
                figure=fig2)
        )]),

    # the third figure div, but this one can be changed
    html.Div([
        html.H1(
            children='Scatter chart: Yearly internationals income per person compare to the Gini index',
            style={'textAlign': 'center','color': colors['text']}),
        # https://dash.plotly.com/basic-callbacks
        html.Div([
            dcc.Graph(
            id='gini_with_income_per_continent'),
            dcc.Slider(
                total_data['year'].min(),
                total_data['year'].max(),
                step=None,
                value=total_data['year'].min(),
                marks={str(year): str(year) for year in total_data['year'].unique()},
                id='year-slider'
            )
        ])
    ])
])

Le code semble plutôt simple, on se perd dans les parenthèses. Cependant lorsqu’on sait faire un peu de HTML / CSS, écrire les balises est plus simple.

4 – Le graphique « dispersé » (Scatter)

Pour ce dernier graphique, c’est le moment d’en mettre plein la vue!

Voici un graphique type « dispersé », contenant 2 axes, des couleurs et des bulles de taille différentes!

Niveau visualisation, il permet de découper certains « groupes » (la plupart des pays Européens ont un index de Gini faible, contrairement à l’Amérique), en plus de permettre des rapprochements variés (on remarque les pays d’Afrique les plus riches sont aussi les plus inégalitaires, ce qui n’est pas le cas de l’Asie).


# that's the same for every graph, unique parameter to change 
@app.callback(
    # graph show
    Output('gini_with_income_per_continent', 'figure'),
    # object to update a graph
    Input('year-slider', 'value'))

# a unique function, even with multiple graphs
def update_figure(selected_year):

    # updated data
    filtered_df = total_data[total_data.year == selected_year]

    # graphic result
    fig3 = px.scatter(
       filtered_df, 
       x="income_per_person",
       y="gini_index",
       size="demox_eiu", 
       color="continent",
       hover_name="country",
       log_x=True, 
       size_max=60
     )

    # change parameters
    fig3.update_layout(transition_duration=300)
    
    return fig3

# to run the server
if __name__ == '__main__':
    app.run_server(debug=True, use_reloader = False) # use_reloader for Jupyter Notebook

Ci-dessus, on peut voir une introduction aux callbacks, le back-end qui permet quelques fonctionnalités rendant notre dashboard interactif (le slider avec les années partant de 2006 à 2016, s’ajoute à cela des données au survol d’une bulle).

Lancer le serveur, cela prend 2 lignes de codes. Avec un Jupyter-Notebook une petite subtilité, « use_reloader = False » pour ne pas faire se relancer le code tout le temps, puis s’interroger « pas de serveur??? WT.??? »

Une conclusion

Test concluant, la prise en main (à l’aide de tutoriaux) se fait sans trop de difficultés. De plus le rendu est satisfaisant. Très bonne librairie gratuite et open-source!

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *