Python enregistrer Plotly tracer au fichier local et insérer dans le html

j'utilise python et plotly pour produire des rapports html interactifs. Ce post donne un joli cadre.

si je produis la trame(via plotly) en ligne, et insère l'url dans le fichier html, cela fonctionne mais rafraîchir les graphiques prend beaucoup de temps. Je me demande si je pourrais produire la carte hors ligne et l'avoir intégrée dans le rapport html, de sorte que la vitesse de chargement n'est pas un problème.

j'ai trouvé que le tracé hors ligne générerait un html pour le diagramme, mais je ne sais pas comment pour l'intégrer dans un autre html. N'importe qui pourrait l'aider?

26
demandé sur Mateo Sanchez 2016-03-28 15:52:29

3 réponses

Option 1: utilisez la fonctionnalité hors ligne de plotly dans votre carnet Jupyter (je suppose que vous utilisez un carnet Jupyter à partir du lien que vous fournissez). Vous pouvez simplement sauvegarder l'ensemble du bloc-notes sous forme de fichier HTML. Quand je fais cela, la seule référence externe est à JQuery; plotly.js sera inlined dans la source HTML.

Option 2: la meilleure façon est probablement de coder directement contre la bibliothèque JavaScript de plotly. La Documentation pour cela peut être trouvée ici: https://plot.ly/javascript/

Hacky Option 3: si vous voulez vraiment continuer à utiliser Python, vous pouvez utiliser un hack pour extraire le HTML qu'il génère. Vous avez besoin d'une version récente de plotly (je l'ai testé avec plotly.__version__ == '1.9.6'). Maintenant, vous pouvez utiliser une fonction interne pour obtenir le HTML généré:

from plotly.offline.offline import _plot_html
data_or_figure = [{"x": [1, 2, 3], "y": [3, 1, 6]}]
plot_html, plotdivid, width, height = _plot_html(
    data_or_figure, False, "", True, '100%', 525)
print(plot_html)

vous pouvez simplement coller la sortie quelque part dans le corps de votre document HTML. Juste assurez-vous d'inclure une référence à plotly dans le tête:

<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>

alternativement, vous pouvez également référencer la version exacte plotly que vous avez utilisée pour générer le HTML ou inline la source JavaScript (qui supprime toutes les dépendances externes; soyez conscient des aspects juridiques cependant).

vous finissez avec un code HTML comme ceci:

<html>
<head>
  <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
  <!-- Output from the Python script above: -->
  <div id="7979e646-13e6-4f44-8d32-d8effc3816df" style="height: 525; width: 100%;" class="plotly-graph-div"></div><script type="text/javascript">window.PLOTLYENV=window.PLOTLYENV || {};window.PLOTLYENV.BASE_URL="https://plot.ly";Plotly.newPlot("7979e646-13e6-4f44-8d32-d8effc3816df", [{"x": [1, 2, 3], "y": [3, 1, 6]}], {}, {"showLink": false, "linkText": ""})</script>
</body>
</html>

Remarque:: Le trait de soulignement au début du nom de la fonction suggère que _plot_html n'est pas destiné à être appelé à partir d'un code externe. Il est donc probable que cette le code cassera avec les versions futures de plotly.

12
répondu JPW 2016-04-02 17:14:57

il y a une meilleure alternative pour l'instant, c'est-à-dire faire un tracé hors ligne dans un div, plutôt qu'un html complet. Cette solution n'implique aucun piratage.

Si vous appelez:

plotly.offline.plot(data, filename='file.html')

Il crée un fichier nommé file.html et il l'ouvre dans votre navigateur web. Toutefois, si vous n':

plotly.offline.plot(data, include_plotlyjs=False, output_type='div')

l'appel retournera une chaîne avec seulement le div nécessaire pour créer les données.

<div id="82072c0d-ba8d-4e86-b000-0892be065ca8" style="height: 100%; width: 100%;" class="plotly-graph-div"></div>
<script type="text/javascript">window.PLOTLYENV=window.PLOTLYENV || {};window.PLOTLYENV.BASE_URL="https://plot.ly";Plotly.newPlot("82072c0d-ba8d-4e86-b000-0892be065ca8", 
[{"y": ..bunch of data..., "x": ..lots of data.., {"showlegend": true, "title": "the title", "xaxis": {"zeroline": true, "showline": true}, 
"yaxis": {"zeroline": true, "showline": true, "range": [0, 22.63852380952382]}}, {"linkText": "Export to plot.ly", "showLink": true})</script>

remarquez que ce n'est qu'une infime partie d'un html que vous sont censés intégrer dans une plus grande page. Pour cela j'utilise un moteur de modèle standard comme Jinga2.

avec ceci vous pouvez créer une page html avec plusieurs graphiques disposés de la façon que vous voulez, et même le retourner comme un réponse du serveur à un appel ajax, très doux.

mise à Jour:

rappelez-vous que vous aurez besoin d'inclure le fichier plotly js pour que tous ces graphiques fonctionnent.

vous pourriez inclure juste avant de mettre le div vous avez obtenu. Si vous mettez ce js en bas de la page, les graphiques ne fonctionne pas.

74
répondu Fermin Silva 2017-01-24 15:38:54

aucune de ces solutions ne fonctionnait. Mon but était de générer des tracés dans un carnet et de les publier dans un autre, de sorte que persister le HTML de parcelle n'était pas aussi important pour moi que d'avoir simplement une méthode pour sérialiser la parcelle au disque pour être reconstruit ailleurs.

la solution que j'ai trouvée est de sérialiser le fig objet en JSON, et ensuite utiliser plotly "json graphique du schéma" pour construire l'intrigue de JSON. Cette démo est entièrement python, mais il devrait être trivial de construisez un tracé en HTML en utilisant cette stratégie de sérialisation JSON et en invoquant directement la bibliothèque javascript plotly, si c'est ce dont vous avez besoin.

import numpy as np
import json
from plotly.utils import PlotlyJSONEncoder
from plotly.offline import download_plotlyjs, init_notebook_mode, iplot
import plotly.graph_objs as go
init_notebook_mode()

def plotlyfig2json(fig, fpath=None):
    """
    Serialize a plotly figure object to JSON so it can be persisted to disk.
    Figures persisted as JSON can be rebuilt using the plotly JSON chart API:

    http://help.plot.ly/json-chart-schema/

    If `fpath` is provided, JSON is written to file.

    Modified from https://github.com/nteract/nteract/issues/1229
    """

    redata = json.loads(json.dumps(fig.data, cls=PlotlyJSONEncoder))
    relayout = json.loads(json.dumps(fig.layout, cls=PlotlyJSONEncoder))

    fig_json=json.dumps({'data': redata,'layout': relayout})

    if fpath:
        with open(fpath, 'wb') as f:
            f.write(fig_json)
    else:
        return fig_json

def plotlyfromjson(fpath):
    """Render a plotly figure from a json file"""
    with open(fpath, 'r') as f:
        v = json.loads(f.read())

    fig = go.Figure(data=v['data'], layout=v['layout'])
    iplot(fig, show_link=False)

## Minimial demo ##

n = 1000
trace = go.Scatter(
    x = np.random.randn(n),
    y = np.random.randn(n),
    mode = 'markers')

fig = go.Figure(data=[trace])
#iplot(fig)
plotlyfig2json(fig, 'myfile.json')
plotlyfromjson('myfile.json')

EDIT: Par discussion sur le github problème, c'est probablement la meilleure approche.

2
répondu David Marx 2018-03-05 23:57:04