Python сохраняет график сюжета в локальный файл и вставляет в html
Я использую Python и плотно для создания интерактивного отчета HTML. Этот пост дает хорошую основу.
Если я создаю график (через plotly) онлайн и вставляю URL в html файл, он работает, но обновление графиков занимает много времени. Интересно, смогу ли я создать график в автономном режиме и включить его в html-отчет, чтобы скорость загрузки не была проблемой.
Я считаю, что график в автономном режиме будет генерировать HTML для диаграммы, но я не знаю, как встроить его в другой HTML. Кто-нибудь может помочь?
Ответы
Ответ 1
Вариант 1. Используйте функциональные возможности в автономном режиме в своем ноутбуке Jupyter (я полагаю, вы используете Jupyter Notebook из предоставляемой вами ссылки). Вы можете просто сохранить весь ноутбук в виде HTML файла. Когда я это делаю, единственная внешняя ссылка - на JQuery; plotly.js будет встроен в источник HTML.
Вариант 2. Лучшим способом, вероятно, является прямое кодирование библиотеки plotly JavaScript. Документацию по этому вопросу можно найти здесь: https://plot.ly/javascript/
Hacky Option 3. Если вы действительно хотите использовать Python, вы можете использовать хак для извлечения HTML-кода, который он создает. Вам нужна последняя версия plotly (я тестировал ее с помощью plotly.__version__ == '1.9.6'
). Теперь вы можете использовать внутреннюю функцию для получения сгенерированного HTML:
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)
Вы можете просто вставить вывод где-нибудь в теле вашего документа HTML. Просто убедитесь, что вы включили ссылку на сюжет в голове:
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
В качестве альтернативы вы также можете ссылаться на точную сюжетную версию, которую вы использовали для генерации HTML или встроенного источника JavaScript (который удаляет любые внешние зависимости, однако, обратите внимание на юридические аспекты).
В итоге вы получите код HTML следующим образом:
<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>
Примечание. Подчеркивание в начале имени функции предполагает, что _plot_html
не должен вызываться из внешнего кода. Поэтому вполне вероятно, что этот код сломается с будущими версиями plotly.
Ответ 2
На данный момент существует лучшая альтернатива, которая заключается в том, чтобы создавать в автономном режиме черчение в div, а не в полный html. Это решение не включает никаких взломов.
Если вы позвоните:
plotly.offline.plot(data, filename='file.html')
Он создает файл с именем file.html
и открывает его в вашем веб-браузере. Однако, если вы делаете:
plotly.offline.plot(data, include_plotlyjs=False, output_type='div')
вызов возвратит строку только с div, необходимым для создания данных, например:
<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>
Обратите внимание, что это всего лишь крошечная часть HTML, которую вы должны встраивать в большую страницу. Для этого я использую стандартный шаблонизатор, такой как Jinga2.
При этом вы можете создать одну html-страницу с несколькими диаграммами, расположенными так, как вам нужно, и даже вернуть ее как ответ сервера на вызов ajax, довольно мило.
Обновить:
Помните, что вам нужно будет включить файл plotly js, чтобы все эти графики работали.
Вы могли бы включить
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
незадолго до того, как положить div у тебя есть. Если вы поместите этот js внизу страницы, графики не будут работать.
Ответ 3
Я не смог заставить ни одно из этих решений работать. Моя цель состояла в том, чтобы сгенерировать графики в одной записной книжке и опубликовать их в другой, поэтому сохранение HTML-кода не было для меня столь же важным, как просто наличие какого-либо метода для сериализации графика на диск, который будет перестроен где-то еще.
Решение, которое я придумал, состоит в том, чтобы сериализовать объект fig
в JSON, а затем использовать сюжетную "схему json chart" для построения графика из JSON. Эта демонстрационная версия полностью на языке Python, но она должна быть тривиальной для построения графика в HTML с использованием этой стратегии JSON-сериализации и прямого вызова библиотеки plotly javascript, если это то, что вам нужно.
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')
РЕДАКТИРОВАТЬ: В обсуждении по связанной проблеме GitHub, это, вероятно, текущий лучший подход.
Ответ 4
В дополнение к другим ответам, другим возможным решением является использование to_json()
на графике.
Нет необходимости в настраиваемом сериализаторе JSON или использовании внутренних решений.
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))
Ответ 5
Чтобы импровизировать приведенный ниже код, вы можете просто вызвать, to_plotly_json() для 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()
Ответ 6
Вы также можете использовать iframe в соответствии с ответом на вопрос , как встраивать html в вывод ipython?
plotly.offline.plot(fig, filename='figure.html',validate=False)
from IPython.display import IFrame
IFrame(src='./figure.html', width=1000, height=600)