Prototyper un dashboard dans Django avec Jupyter Lab

22 mai 2023 12:55 dans data-pipelines / publications
Slider Image

Passons à l'analyse de données. L'interactivité du notebook va nous permettre de prototyper des charts. Nous verrons ensuite comment les distribuer dans Django.

Créer des charts en notebook

La flexibilité du format notebook nous permet d'explorer différentes possibilités et de prototyper à volonté. Commençons par un chart simple. Chargeons d'abord de la donnée dans une dataframe à partir d'un query:

import dataspace
        from trades.models import Trade

        qs = Trade.objects.filter(market="Binance", side="buy").order_by("date")[:50000]
        ds = dataspace.from_django(qs)  
        ds.show()
      

Dessinons un simple line chart à partir de cette donnée:


        ds.axis("date:T", "price:Q")
        ds.line_()
      

Exporter des charts

Les chart Altair peuvent s'exporter de différentes manières. Nous allons ici nous concentrer sur une méthode simple afin de voir comment intégrer cela dans un data pipeline. Nous allons exporter une image png, afin de pouvoir l'intégrer facilement en html dans un dashboard:


        chart = ds.line_()
        chart.save('chart.png')
      

Bien que pratique cette méthode présente l'inconvénient de ne pas préserver l'interactivité du chart. Nous verrons ultérieurement comment exporter le chart en json au format Vega Lite à cet effet.

Prototypage du dashboard

Nous allons créer des fonctions chargées de générer des charts en png et les intégrer dans une management command. Créons quelques charts plus complexes en utilisant un sample de la data:


        qs = Trade.objects.all()[:1000]
        ds = dataspace.from_django(qs)  
        ds.sort("date")
        ds.to_str("date")
        ds.show()
      

Vue sur tous les marchés:


        ds.axis("date:T", "price:Q")
        ds.point_(encode={"shape":'market:N', "color":"side:N"})
      

Vue en facettes sur tous les marchés:


        ds.square_(encode={"color":"side:N"}).wh(350,100).facet(
            facet='market:N',
            columns=3
        )
      

Créons une fonction à partir de tout cela pour cette classe de charts:

defmarkets_charts(export_path: str):# load data
          qs = Trade.objects.all()[:1000]
          ds = dataspace.from_django(qs)  
          # transform
          ds.sort("date")
          ds.to_str("date")
          # chart
          ds.axis("date:T", "price:Q")
          c = ds.point_(encode={
              "shape":'market:N',
              "color":"side:N"
          })
          c2 = ds.square_(encode={
              "color":"side:N"
          }).wh(350,100).facet(
              facet='market:N',
              columns=3
          )
          # export
          c.save(export_path + "all_markets.png")
          c2.save(export_path + "faceted_markets.png")
    

Cette fonction constituera une brique du data pipeline chargée de générer périodiquement les charts. Créons maintenant le pipeline lui-même.

Le data pipeline

Dans l'app trades créons un dossier pipeline contenant un fichier __init__.py. Plaçons la fonction ci-dessus dans un fichier charts.py et créons le pipeline dans le fichier __init__:

from .charts import markets_charts, activity_chart
        from django.conf import settings


        defrun(verbose: bool = False):
            path = str(settings.BASE_DIR.absolute()) + "/static/charts"if verbose isTrue:
                print("Creating markets charts")
            markets_charts(path)
            if verbose isTrue:
                print("Creating activity chart")
            activity_chart(path)
      

Les charts seront sauvés dans static/charts ici. Ajuster en fonction du projet. Nous n'avons plus qu'à créer une management command pour lancer le pipeline. Dans trades/management/commands/data_pipeline.py :

from django.core.management.base import BaseCommand
        from trades.pipeline import run as run_pipeline


        classCommand(BaseCommand):help = "Run the data pipeline ang generate the charts"defhandle(self, *args, **options):
                verbose = options["verbosity"] == 1if verbose:
                    print("Running data pipeline")
                run_pipeline(verbose=verbose)
                if verbose:
                    print("Finished running data pipeline")
      

Lancer la commande:


        python manage.py data_pipeline
      

Servir le dashboard

Nous n'avons plus qu'à créer un template pour afficher les charts en png:


        {% load static %}

        <h1>Dashboard</h1><h2>Markets detail</h2><p><imgsrc="{% static 'charts/all_markets.png' %}"alt="" /></p><p><imgsrc="{% static 'charts/faceted_markets.png' %}"alt="" /></p>

Conclusion

L'approche data pipeline permet de générer statiquement des charts en une fois, par exemple en lançant la management command depuis un cron job. Cette approche est avantageuse pour une dashboard complexe avec beaucoup de données et de charts.

Cependant pour des données mises à jour plus fréquemment une approche de génération des charts à la demande peut s'avérer nécessaire. Nous allons voir dans les articles suivants comment aborder cette problématique et comment obtenir des charts Altair interactifs.

Note: le code exemple utilisé dans cet article est disponible dans le repository django-datastack

Crédit : image générée par Midjourney

Articles associés

Utiliser une IA locale dans Django

Ceci est une introduction l'IA prend de plus en plus de place, de plus en plus vite. Depuis quelques temps a émergé un mouvement open source autour notamment de Llama.cpp.

Django et IA locale : connecter Langchain