cono001
Estoy usando python y plotly para producir un informe html interactivo. Esta publicación da un buen marco.
Si produzco el gráfico (a través de plotly) en línea e inserto la URL en el archivo html, funciona, pero actualizar los gráficos lleva mucho tiempo. Me pregunto si podría producir el gráfico fuera de línea e incrustarlo en el informe html, para que la velocidad de carga no sea un problema.
Encuentro que plot offline generaría un html para el gráfico, pero no sé cómo incrustarlo en otro html. ¿Alguien podría ayudar?
Fermín Silva
Hay una mejor alternativa a partir de ahora, que es trazar fuera de línea en un div, en lugar de un html completo. Esta solución no implica ningún truco.
Si llamas:
plotly.offline.plot(data, filename="file.html")
Crea un archivo llamado file.html
y lo abre en su navegador web. Sin embargo, si lo hace:
plotly.offline.plot(data, include_plotlyjs=False, output_type="div")
la llamada devolverá una cadena con solo el div requerido para crear los datos, por ejemplo:
<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>
Observe cómo es solo una pequeña porción de un html que se supone que debe incrustar en una página más grande. Para eso utilizo un motor de plantillas estándar como Jinga2.
Con esto, puede crear una página html con varios gráficos dispuestos de la manera que desee, e incluso devolverla como un respuesta del servidor a una llamada ajaxmuy dulce.
Actualizar:
Recuerde que deberá incluir el archivo plotly js para que todos estos gráficos funcionen.
podrías incluir
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
justo antes de poner el div que tienes. Si coloca este js en la parte inferior de la página, los gráficos no funcionará.
-
Gracias. Su respuesta aquí contenía la línea crucial, “Podría incluir
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
justo antes de poner el div que obtuviste”, lo que resolvió el problema para mí.– 0_0
24/01/2017 a las 15:30
-
@0_0 tienes razón. No incluí esa parte aquí porque ya se mencionó en la respuesta anterior. Lo agregaré aquí también para futuras referencias.
– Fermín Silva
24 de enero de 2017 a las 15:38
-
Me pregunto por qué mantienen estas cosas simples como huevos de pascua en la documentación … ¡más 100 a esta respuesta! 🙂
– Editor novato
1 de marzo de 2017 a las 5:22
-
@Fermin Silva ¿Puede dar un ejemplo de cómo devolver/usar ese valor devuelto en una llamada ajax?
– Mahdi Guelichi
23 de marzo de 2019 a las 1:23
-
@MahdiGhelichi necesitas
eval
el código que obtiene de ajax, porque simplemente agregar el html al DOM no funcionará. Echa un vistazo a subinsb.com/how-to-execute-javascript-in-ajax-response (y también tenga en cuenta que ejecutar js a ciegas desde un servidor puede ser un poco inseguro)– Fermín Silva
26 de marzo de 2019 a las 16:33
JPW
Opción 1: use la funcionalidad fuera de línea de plotly en su Jupyter Notebook (supongo que está usando un Jupyter Notebook desde el enlace que está proporcionando). Simplemente puede guardar todo el cuaderno como un archivo HTML. Cuando hago esto, la única referencia externa es a JQuery; plotly.js se insertará en la fuente HTML.
opcion 2: La mejor manera es probablemente codificar directamente contra la biblioteca de JavaScript de plotly. La documentación para esto se puede encontrar aquí: https://plot.ly/javascript/
Actualizar: Llamar a una función interna nunca ha sido una buena idea. Recomiendo usar el enfoque dado por @Fermin Silva. En las versiones más nuevas, ahora también hay una función dedicada para esto: plotly.io.to_html
(ver https://plotly.com/python-api-reference/generated/plotly.io.to_html.html)
Hacky Opción 3 (versión original solo como referencia): si realmente desea continuar usando Python, puede usar algún truco para extraer el HTML que genera. Necesitas una versión reciente de plotly (la probé con plotly.__version__ == '1.9.6'
). Ahora, puede usar una función interna para obtener el HTML generado:
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)
Simplemente puede pegar el resultado en algún lugar del cuerpo de su documento HTML. Solo asegúrese de incluir una referencia a plotly en la cabeza:
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
Alternativamente, también puede hacer referencia a la versión gráfica exacta que usó para generar el HTML o en línea la fuente de JavaScript (que elimina cualquier dependencia externa; sin embargo, tenga en cuenta los aspectos legales).
Terminas con un código HTML como este:
<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>
Nota: El guión bajo al comienzo del nombre de la función sugiere que _plot_html
no está destinado a ser llamado desde un código externo. Por lo tanto, es probable que este código se rompa con futuras versiones de plotly.
-
En mi prueba del diagrama de Sankey,
_plot_html
genera menos código queplotly.offline.plot(data, filename='file.html')
, el último parece contener valores predeterminados en JSON. js api permite actualizar el gráfico de manera más eficiente después de la creación, la definición json es la misma que en python, esta es una buena opción;– ben
6 de abril de 2019 a las 2:18
-
@JPW ¿Cómo funciona esto ahora dado que _plot_html está en desuso?
– GKS
29 de marzo de 2020 a las 17:02
Además de las otras respuestas, otra posible solución es usar to_json()
en la figura gráfica.
No es necesario un serializador JSON personalizado ni el uso de soluciones internas.
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))
-
¿Puedes pasar varias parcelas a la plantilla html de esta manera?
– aerijman
3 de febrero de 2020 a las 19:29
-
@Maximiliano Peters Lo hizo. gracias. No presté atención a la forma en que se pasan las variables a la cadena con el formato de python. ¡La tuya es la respuesta más limpia y única que funcionó rápido para mí!
– aerijman
3 de febrero de 2020 a las 20:06
Pensé que la respuesta necesita una actualización basada en una versión reciente. (trazado==4.9.0)
fig.write_html("path/to/file.html")
referencia: documentación gráfica
david marx
No pude hacer que ninguna de estas soluciones funcionara. Mi objetivo era generar diagramas en un cuaderno y publicarlos en otro, por lo que mantener el HTML del diagrama no era tan importante para mí como simplemente tener algún método para serializar el diagrama en el disco para reconstruirlo en otro lugar.
La solución que se me ocurrió es serializar el fig
objeto a JSON, y luego use el “esquema de gráfico json” de plotly para construir el gráfico a partir de JSON. Esta demostración es todo python, pero debería ser trivial construir una trama en HTML utilizando esta estrategia de serialización JSON e invocando directamente la biblioteca plotly javascript, si eso es lo que necesita.
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')
EDITAR: por discusión sobre el github asociado temaeste es probablemente el mejor enfoque actual.
-
@Wayne No creo que sea correcto. OP especificó que están tratando de incrustar un interactivo gráfico, mientras que la función de exportación de imágenes estáticas, por definición, no es interactiva (es decir, la imagen es “estática”).
–David Marx
4 de junio de 2019 a las 19:29
VarunVk
La forma más fácil es usar Pío de la trama
import plotly.io as pio
pio.write_html(fig, file="Name.html", auto_open=True)
Lo he usado muchísimo para almacenar mis gráficos antes de reuniones importantes
-
@Wayne No creo que sea correcto. OP especificó que están tratando de incrustar un interactivo gráfico, mientras que la funcionalidad de exportación de imágenes estáticas, por definición, no es interactiva (es decir, la imagen es “estática”).
–David Marx
4 de junio de 2019 a las 19:29
Pablo Rougieux
También puede usar un iframe de acuerdo con una respuesta a la pregunta ¿cómo incrustar html en la salida de ipython?
plotly.offline.plot(fig, filename="figure.html",validate=False)
from IPython.display import IFrame
IFrame(src="https://stackoverflow.com/questions/36262748/./figure.html", width=1000, height=600)