web-dev-qa-db-fra.com

python enregistrer le tracé de la parcelle dans un fichier local et l'insérer dans un fichier HTML

J'utilise python et complotement pour produire un rapport html interactif. Ce post donne un cadre agréable.

Si je produis le tracé (via plotly) en ligne et que j'insère l'URL dans le fichier html, cela fonctionne, mais l'actualisation des graphiques prend beaucoup de temps. Je me demande si je pourrais produire le graphique hors ligne et l’intégrer dans le rapport HTML, afin que la vitesse de chargement ne pose pas de problème.

Je trouve l'intrigue hors ligne générerait un code HTML pour le graphique, mais je ne sais pas comment l'intégrer dans un autre code HTML. Quelqu'un pourrait aider?

39
cone001

Option 1 : utilisez la fonctionnalité hors connexion de plotly dans votre carnet Jupyter (je suppose que vous utilisez un carnet Jupyter à partir du lien que vous fournissez). Vous pouvez simplement sauvegarder le bloc-notes entier dans un fichier HTML. Lorsque je fais cela, la seule référence externe est JQuery; plotly.js sera inséré dans la source HTML.

Option 2 : Le meilleur moyen est probablement de coder directement contre la bibliothèque JavaScript de plotly. La documentation à ce sujet 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 code HTML qu'il génère. Vous avez besoin d’une version récente de plotly (je l’ai testée avec plotly.__version__ == '1.9.6'). Maintenant, vous pouvez utiliser une fonction interne pour obtenir le code 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. Assurez-vous simplement d'inclure une référence à complot dans la tête:

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

Alternativement, vous pouvez également référencer la version exacte du graphique que vous avez utilisée pour générer le code HTML ou insérer le code source JavaScript (ce qui supprime toute dépendance externe; tenez compte toutefois des aspects juridiques).

Vous vous retrouvez avec un code HTML comme celui-ci:

<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é depuis un code externe. Il est donc probable que ce code rompt avec les futures versions de plotly.

21
JPW

Il existe une meilleure alternative à l'heure actuelle, qui consiste à effectuer un traçage hors ligne dans une 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 l'ouvre dans votre navigateur Web. Cependant, si vous le faites:

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

l'appel retournera une chaîne avec seulement le div requis pour créer les données, par exemple:

<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 comme c'est juste une infime partie d'un code HTML que vous êtes censé intégrer dans une page plus grande. Pour cela, j'utilise un moteur de template standard comme Jinga2.

Avec cela, vous pouvez créer une page html avec plusieurs graphiques disposés comme vous le souhaitez, et même la renvoyer sous forme de réponse du serveur à un appel ajax, plutôt sympa.

Mise à jour:

N'oubliez pas que vous devez inclure le fichier plotly js pour que tous ces graphiques fonctionnent.

Vous pourriez inclure

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

juste avant de mettre le div que vous avez. Si vous mettez ce js au bas de la page, les graphiques ne fonctionneront pas .

110
Fermin Silva

Je n'ai pas réussi à obtenir l'une de ces solutions. Mon objectif était de générer des tracés dans un ordinateur portable et de les publier dans un autre. Conserver l'intrigue HTML n'a donc pas été aussi important pour moi que de disposer d'une méthode permettant de sérialiser l'intrigue sur un disque et de le reconstruire ailleurs.

La solution que j’ai proposée consiste à sérialiser l’objet fig en JSON, puis à utiliser le "schéma json chart" de Plotly pour construire le tracé à partir de JSON. Cette démo est entièrement python, mais il devrait être simple de créer un tracé en HTML à l'aide de cette stratégie de sérialisation JSON et d'appeler directement la bibliothèque javascript de 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 associé numéro , c'est probablement la meilleure approche actuelle.

7
David Marx

En plus des autres réponses, une autre solution possible consiste à utiliser to_json() sur la figure de complot.

Pas besoin de sérialiseur JSON personnalisé ni d'utilisation de solutions internes.

import plotly

# create a simple plot
bar = plotly.graph_objs.Bar(x=['giraffes', 'orangutans', 'monkeys'], 
                            y=[20, 14, 23])
layout = plotly.graph_objs.Layout()
fig = plotly.graph_objs.Figure([bar], layout)

# convert it to JSON
fig_json = fig.to_json()

# a simple HTML template
template = """<html>
<head>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
    <div id='divPlotly'></div>
    <script>
        var plotly_data = {}
        Plotly.react('divPlotly', plotly_data.data, plotly_data.layout);
    </script>
</body>

</html>"""

# write the JSON to the HTML template
with open('new_plot.html', 'w') as f:
    f.write(template.format(fig_json))
2
Maximilian Peters

Pour improviser le code ci-dessous, vous pouvez simplement appeler to_plotly_json () pour ex :,

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


--------------------------------------------
Simple way:

fig = go.Figure(data=['data'], layout=['layout'])
fig.to_plotly_json()    

1
sohail