Python >> Tutoriel Python >  >> Python Tag >> Bokeh

Graphiques à barres réactifs avec Bokeh, Flask et Python 3

Bokeh est une puissante bibliothèque Python open source qui permet aux développeurs de générer des visualisations de données JavaScript pour leurs applications Web sans écrire de JavaScript . Bien qu'il puisse être utile d'apprendre une bibliothèque de visualisation de données basée sur JavaScript comme d3.js, il est souvent beaucoup plus facile de supprimer quelques lignes de code Python pour faire le travail.

Avec Bokeh, nous pouvons créer des visualisations interactives incroyablement détaillées, ou simplement des visualisations traditionnelles comme le graphique à barres suivant.

Utilisons le framework Web Flask avec Bokeh pour créer des graphiques à barres personnalisés dans une application Web Python.

Nos outils

Ce tutoriel fonctionne avec Python 2 ou 3, mais Python 3 est fortement recommandé pour les nouvelles applications. J'ai utilisé Python 3.6.1 lors de la rédaction de cet article. En plus de Python tout au long de ce didacticiel, nous utiliserons également les dépendances d'application suivantes :

  • Frame Web Flask, version 0.12.2
  • Bibliothèque de visualisation de données Bokeh, version 0.12.5
  • structures de données pandas et bibliothèque d'analyse, version 0.20.1
  • pip et virtualenv, qui sont fournis avec Python 3, pour installer et isoler les bibliothèques Flask, Bokeh et pandas de tout autre projet Python sur lequel vous pourriez travailler

Si vous avez besoin d'aide pour configurer votre environnement de développement avant d'exécuter ce code, consultez ce guide pour configurer Python 3 et Flask sur Ubuntu 16.04 LTS

Tout le code de cet article de blog est disponible en open source sous la licence MIT sur GitHub sous le répertoire bar-charts-bokeh-flask-python-3 du référentiel blog-code-examples. Utilisez et abusez du code source comme vous le souhaitez pour vos propres applications .

Installer Bokeh et Flask

Créez un nouvel environnement virtuel pour ce projet afin d'isoler nos dépendances à l'aide de la commande suivante dans le terminal. J'exécute généralement cette commande dans un venvs séparé répertoire où tous mes virtualenvsare stockent.

python3 -m venv barchart

Activez l'environnement virtuel.

source barchart/bin/activate

L'invite de commande changera après l'activation de virtualenv :

Gardez à l'esprit que vous devez activer le virtualenv dans chaque nouvelle fenêtre de terminal où vous souhaitez utiliser le virtualenv pour exécuter le projet.

Bokeh et Flask peuvent être installés dans le pip virtualenvusing maintenant activé. Exécutez cette commande pour obtenir les versions Bokeh et Flask appropriées.

pip install bokeh==0.12.5 flask==0.12.2 pandas==0.20.1

Après une brève période de téléchargement et d'installation, nos dépendances requises doivent être installées dans notre environnement virtuel. Recherchez la sortie pour confirmer que tout a fonctionné.

Installing collected packages: six, requests, PyYAML, python-dateutil, MarkupSafe, Jinja2, numpy, tornado, bokeh, Werkzeug, itsdangerous, click, flask, pytz, pandas
  Running setup.py install for PyYAML ... done
  Running setup.py install for MarkupSafe ... done
  Running setup.py install for tornado ... done
  Running setup.py install for bokeh ... done
  Running setup.py install for itsdangerous ... done
Successfully installed Jinja2-2.9.6 MarkupSafe-1.0 PyYAML-3.12 Werkzeug-0.12.2 bokeh-0.12.5 click-6.7 flask-0.12.2 itsdangerous-0.24 numpy-1.12.1 pandas-0.20.1 python-dateutil-2.6.0 pytz-2017.2 requests-2.14.2 six-1.10.0 tornado-4.5.1

Nous pouvons maintenant commencer à créer notre application Web.

Démarrage de notre application Flask

Nous allons d'abord coder une application Flask de base, puis ajouter notre graphique à barres à la page rendue.

Créez un dossier pour votre projet puis créez-y un fichier nommé app.py avec ces contenus initiaux :

from flask import Flask, render_template


app = Flask(__name__)


@app.route("/<int:bars_count>/")
def chart(bars_count):
    if bars_count <= 0:
        bars_count = 1
    return render_template("chart.html", bars_count=bars_count)


if __name__ == "__main__":
    app.run(debug=True)

Le code ci-dessus est une courte application Flask à route unique qui définit le chart fonction. chart prend un nombre entier arbitraire en entrée qui sera utilisé plus tard pour définir la quantité de données que nous voulons dans notre graphique à barres. Le render_template fonction dans chart utilisera un modèle du moteur de modèle par défaut de Flask nommé Jinja2 pour générer du HTML.

Les deux dernières lignes du nous permettent d'exécuter l'application Flask à partir de la ligne de commande sur le port 5000 en mode débogage. N'utilisez jamais le mode débogage pour la production, c'est pour cela que les serveurs WSGI comme Gunicorn sont conçus.

Créez un sous-répertoire dans votre dossier de projet nommé templates . Dans les templates créer un nom de fichier chart.html . chart.html a été référencé dans le chart fonction de notre app.py fichier, nous devons donc le créer avant que notre application ne s'exécute correctement. Remplir chart.html avec le balisage Jinja2 suivant.

<!DOCTYPE html>
<html>
  <head>
    <title>Bar charts with Bokeh!</title>
  </head>
  <body>
    <h1>Bugs found over the past {{ bars_count }} days</h1>
  </body>
</html>

chart.html Le passe-partout de affiche le nombre de barres passées dans le chart fonction via l'URL.

Le <h1> Le message de la balise sur le nombre de bugs trouvés va de pair avec le thème de notre exemple d'application. Nous ferons semblant de tracer le nombre de bugs trouvés par les tests automatisés exécutés chaque jour.

Nous pouvons tester notre application maintenant.

Assurez-vous que votre virtualenv est toujours activé et que vous êtes dans le répertoire de base de votre projet où app.py est situé. Exécutez app.py en utilisant le python commande.

$(barchart) python app.py

Accédez à localhost:5000/16/ dans votre navigateur Web. Vous devriez voir un gros message qui change lorsque vous modifiez l'URL.

Notre route Flask simple est en place mais ce n'est pas très excitant. Il est temps d'ajouter notre graphique à barres.

Générer le graphique à barres

Nous pouvons nous appuyer sur la base de base de l'application Flask que nous venons d'écrire avec un nouveau code Python qui utilise Bokeh.

Ouvrez app.py sauvegarder et modifier le haut du fichier pour inclure les importations suivantes.

import random
from bokeh.models import (HoverTool, FactorRange, Plot, LinearAxis, Grid,
                          Range1d)
from bokeh.models.glyphs import VBar
from bokeh.plotting import figure
from bokeh.charts import Bar
from bokeh.embed import components
from bokeh.models.sources import ColumnDataSource
from flask import Flask, render_template

Dans le reste du fichier, nous aurons besoin de ces importations Bokeh avec le random module pour générer des données et notre graphique à barres.

Notre graphique à barres utilisera les "bugs logiciels trouvés" comme thème. Les données seront générées aléatoirement à chaque rafraîchissement de la page. Dans une application réelle, vous auriez une source de données plus stable et plus utile !

Continuer à modifier app.py donc la section après les importations ressemble au code suivant.

app = Flask(__name__)


@app.route("/<int:bars_count>/")
def chart(bars_count):
    if bars_count <= 0:
        bars_count = 1

    data = {"days": [], "bugs": [], "costs": []}
    for i in range(1, bars_count + 1):
        data['days'].append(i)
        data['bugs'].append(random.randint(1,100))
        data['costs'].append(random.uniform(1.00, 1000.00))

    hover = create_hover_tool()
    plot = create_bar_chart(data, "Bugs found per day", "days",
                            "bugs", hover)
    script, div = components(plot)

    return render_template("chart.html", bars_count=bars_count,
                           the_div=div, the_script=script)

Le chart La fonction gagne trois nouvelles listes qui sont générées aléatoirement par le module random super pratique de Python 3.

chart appelle deux fonctions, create_hover_tool et create_bar_chart .Nous n'avons pas encore écrit ces fonctions, alors continuez à ajouter du code sous chart :

def create_hover_tool():
    # we'll code this function in a moment
    return None


def create_bar_chart(data, title, x_name, y_name, hover_tool=None,
                     width=1200, height=300):
    """Creates a bar chart plot with the exact styling for the centcom
       dashboard. Pass in data as a dictionary, desired plot title,
       name of x axis, y axis and the hover tool HTML.
    """
    source = ColumnDataSource(data)
    xdr = FactorRange(factors=data[x_name])
    ydr = Range1d(start=0,end=max(data[y_name])*1.5)

    tools = []
    if hover_tool:
        tools = [hover_tool,]

    plot = figure(title=title, x_range=xdr, y_range=ydr, plot_width=width,
                  plot_height=height, h_symmetry=False, v_symmetry=False,
                  min_border=0, toolbar_location="above", tools=tools,
                  responsive=True, outline_line_color="#666666")

    glyph = VBar(x=x_name, top=y_name, bottom=0, width=.8,
                 fill_color="#e12127")
    plot.add_glyph(source, glyph)

    xaxis = LinearAxis()
    yaxis = LinearAxis()

    plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker))
    plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker))
    plot.toolbar.logo = None
    plot.min_border_top = 0
    plot.xgrid.grid_line_color = None
    plot.ygrid.grid_line_color = "#999999"
    plot.yaxis.axis_label = "Bugs found"
    plot.ygrid.grid_line_alpha = 0.1
    plot.xaxis.axis_label = "Days after app deployment"
    plot.xaxis.major_label_orientation = 1
    return plot

Il y a beaucoup de nouveau code ci-dessus, alors décomposons-le. Lecreate_hover_tool la fonction ne fait rien pour le moment, elle renvoie simplement None , que nous pouvons utiliser si nous ne voulons pas d'outil de survol. Le hovertool est une superposition qui apparaît lorsque nous déplaçons le curseur de notre souris sur l'une des barres ou touchons une barre sur un écran tactile afin que nous puissions voir plus de données sur la barre.

Dans le create_bar_chart fonction que nous prenons dans notre source de données générée et la convertissons en un ColumnDataSource objet qui est un type d'objet d'entrée que nous pouvons passer aux fonctions Bokeh. Nous spécifions deux plages pour les axes x et y du graphique.

Comme nous n'avons pas encore d'outil de survol, le tools la liste restera vide. La ligne où nous créons plot en utilisant le figure la fonction est l'endroit où une grande partie de la magie se produit. Nous spécifions tous les paramètres que nous voulons que notre graphique ait tels que la taille, la barre d'outils, les bordures et si le graphique doit ou non être réactif lors du changement de la taille du navigateur Web.

Nous créons des barres verticales avec le VBar objet et ajoutez-les au tracé en utilisant le add_glyph fonction qui combine nos données source avec le VBar spécification.

Les dernières lignes de la fonction modifient l'apparence du graphique. Par exemple j'ai enlevé le Bokeh logo en spécifiant plot.toolbar.logo = None et ajouté des étiquettes aux deux axes. Je vous recommande de garder la documentation bokeh.plottinouverte pour connaître vos options de personnalisation de vos visualisations.

Nous avons juste besoin de quelques mises à jour de notre templates/chart.html fichier pour afficher la visualisation. Ouvrez le fichier et ajoutez ces 6 lignes au fichier. Deux de ces lignes sont pour le CSS requis, deux sont des fichiers Bokeh JavaScript et les deux autres sont le graphique généré.

<!DOCTYPE html>
<html>
  <head>
    <title>Bar charts with Bokeh!</title>
    <link href="http://cdn.pydata.org/bokeh/release/bokeh-0.12.5.min.css" rel="stylesheet">
    <link href="http://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.0.min.css" rel="stylesheet">
  </head>
  <body>
    <h1>Bugs found over the past {{ bars_count }} days</h1>
    {{ the_div|safe }}
    <script src="http://cdn.pydata.org/bokeh/release/bokeh-0.12.5.min.js"></script>
    <script src="http://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.5.min.js"></script>
    {{ the_script|safe }}
  </body>
</html>

Très bien, essayons notre application avec un simple graphique de 4 barres. L'application TheFlask devrait se recharger automatiquement lorsque vous enregistrez app.py avec le nouveau code mais si vous arrêtez le serveur de développement, relancez-le avec le python app.py commande.

Ouvrez votre navigateur sur localhost :5000/4/.

Celui-ci a l'air un peu clairsemé, nous pouvons donc l'augmenter de 4x à 16 bars en allant sur localhost:5000/16/.

Maintenant, un autre 4x à 128 bars avec localhost :5000/128/...

Ça a l'air bien jusqu'à présent. Mais qu'en est-il de cet outil de survol pour explorer chaque barre pour plus de données ? Nous pouvons ajouter le survol avec seulement quelques lignes de code dans le create_hover_tool fonction.

Ajout d'un outil de survol

Dans app.py modifier le create_hover_tool pour correspondre au code suivant.

def create_hover_tool():
    """Generates the HTML for the Bokeh's hover data tool on our graph."""
    hover_html = """
      <div>
        <span class="hover-tooltip">$x</span>
      </div>
      <div>
        <span class="hover-tooltip">@bugs bugs</span>
      </div>
      <div>
        <span class="hover-tooltip">[email protected]{0.00}</span>
      </div>
    """
    return HoverTool(tooltips=hover_html)

Cela peut sembler vraiment étrange d'avoir du HTML intégré dans votre application Python, mais c'est ainsi que nous spécifions ce que l'outil de survol doit afficher. Nous utilisons$x pour afficher l'axe x de la barre, @bugs pour afficher le champ "bugs" de notre source de données, et [email protected]{0.00} pour afficher le champ "coûts" sous la forme d'un montant en dollars avec exactement 2 décimales.

Assurez-vous d'avoir changé return None à return HoverTool(tooltips=hover_html) afin que nous puissions voir les résultats de notre nouvelle fonction dans le graphique.

Revenez au navigateur et rechargez la page localhost:5000/128/.

Bon travail! Essayez de jouer avec le nombre de barres dans l'URL et la taille de la fenêtre pour voir à quoi ressemble le graphique dans différentes conditions.

Le graphique est encombré de plus de 100 barres environ, mais vous pouvez l'essayer avec le nombre de barres que vous souhaitez. Voici à quoi ressemble une quantité pratique de 50 000 bars, juste pour le plaisir :

Oui, nous devrons peut-être faire un travail supplémentaire pour afficher plus de quelques centaines de barres à la fois.

Quelle est la prochaine ?

Vous venez de créer un chouette graphique à barres configurable dans Bokeh. Ensuite, vous pouvez modifier le jeu de couleurs, changer la source de données d'entrée, essayer de créer d'autres types de graphiques ou résoudre comment afficher un très grand nombre de barres.

Il y a bien plus que ce que Bokeh peut faire, alors assurez-vous de consulter la documentation officielle du projet, le référentiel GitHub, la page Full Stack Python Bokeh ou jetez un œil à d'autres sujets sur Full Stack Python.

Des questions? Faites-le moi savoir via un ticket de problème GitHub sur le référentiel Full Stack Python, sur Twitter@fullstackpythonou @mattmakai.

Vous voyez quelque chose qui ne va pas dans cet article de blog ? La source de cette page sur GitHuband soumet une pull request.