2016-03-28 459 views
14

我正在使用python并绘制产生交互式html报告。这篇文章给出了一个很好的框架(http://moderndata.plot.ly/generate-html-reports-with-python-pandas-and-plotly/)。python保存绘图到本地文件并插入到html

如果我通过在线生成绘图(并通过绘图)并将该url插入到html文件中,它可以正常工作,但刷新图表需要很长时间。我想知道我是否可以离线制作图表并将其嵌入到html报告中,以便加载速度不成问题。

我发现离线图会为图表生成一个html,但我不知道如何将它嵌入到另一个html中。任何人可以帮忙?

回答

7

选项1:在Jupyter笔记本中使用plotly的脱机功能(我想你是从你提供的链接中使用Jupyter笔记本)。您可以简单地将整个笔记本保存为HTML文件。当我这样做时,唯一的外部参考是JQuery; plotly.js将在HTML源代码中内联。

选项2:最好的方法是直接对plotly的JavaScript库进行编码。该文件可以在这里找到:https://plot.ly/javascript/

哈克选项3:如果你真的想继续使用Python,你可以使用一些黑客来提取它生成的HTML。你需要一些最近的版本(我用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文档正文中的输出。只要确保您在头一个参考plotly:

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

另外,您也可以参考您用来生成HTML或内联JavaScript源(其中删除任何外部依赖的确切plotly版本;是但是了解法律方面)。

你结束了一些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并不意味着从外部代码调用。所以这个代码很可能会与未来版本的情节打破。

53

现在有一个更好的选择,那就是离线绘制到div而不是完整的HTML。 此解决方案不涉及任何黑客行为。

如果您拨打:

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

它创建了一个名为file.html文件,并在Web浏览器中打开它。但是,如果你这样做:

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文件。

你可以包括之前把你的股利。如果您将此js放在页面底部,图表将不起作用

+5

谢谢。你的回答[这里](http://stackoverflow.com/a/38033016/1185293)包含了一个关键线,“你可以包括''就在把你的div放好之前。”,这为我解决了这个问题。 –

+0

@ 0_0你是对的。我没有在这里包括那部分,因为在上面的答案中已经提到过了。我会在这里添加它,以及将来的参考 –

+0

我想知道他们为什么保持这些简单的东西作为复活节彩蛋在那里的文档....加100这个答案! :) – NoobEditor

0

我没有能够得到任何这些解决方案的工作。我的目标是在一个笔记本上生成地块,并将它们发布到另一个笔记本中,因此坚持HTML的情节对于我来说并不重要,因为它只是有一些将剧情序列化到磁盘以在其他地方重建的方法。

我想出的解决方案是将fig对象序列化为JSON,然后使用plotly的“json图表模式”从JSON构建图表。这个演示全部是python,但使用这个JSON序列化策略在HTML中构建一个情节并直接调用剧情的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上issue讨论,这可能是目前最好的办法。

相关问题