Better Plotting with Plotly

栏目: IT技术 · 发布时间: 5年前

内容简介:and ending at another part that we know immediately follows the last part we needLet's print out our substring to see what we've ended up with.If we replace every occurrence of the original ID,

In [2]:

extern crate plotly;
extern crate nanoid;

use plotly::charts::{Mode, Scatter};
use plotly::Plot;
use nanoid::nanoid;
use std::fs;

let plotly_file = "temp_plot.html";

In the last section, we covered how to get plotting with Ploty using Plotly for Rust paired with our very own workaround. If you continued experimenting with this approach before starting this section you may have encountered some limitations:

  • File size . The notebook file from the previous section, plotting-with-plotly.ipynb , weighed in at around $3.4$ MB. This is an unusually large file for what was only a few paragraphs and a single interactive plot.
  • Multiple plots . If you tried to output a second Plotly plot in the same notebook, only the first one would be rendered.
  • File size, again . If you did solve the issue regarding multiple plots, your file size would grow linearly for every plot output. A second plot would take you from $3.4$ MB to $6.8$ MB.

We're going to improve our workaround so that we can produce many of our nice interactive plots without bloating our notebooks and any HTML files we may save to.

Example Plotly Plot

Let's use the code from the previous section to generate our plot. We will then save this to a file as HTML, and load it back into a string for further processing.

In [3]:

let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![10, 15, 13, 17])
    .name("trace1")
    .mode(Mode::Markers);
let trace2 = Scatter::new(vec![2, 3, 4, 5], vec![16, 5, 11, 9])
    .name("trace2")
    .mode(Mode::Lines);
let trace3 = Scatter::new(vec![1, 2, 3, 4], vec![12, 9, 15, 12]).name("trace3");

let mut plot = Plot::new();

plot.add_trace(trace1);
plot.add_trace(trace2);
plot.add_trace(trace3);

plot.to_html(plotly_file);

let plotly_contents = fs::read_to_string(plotly_file).unwrap();

Reducing the File Size

If you open the HTML output that was saved to temp_plot.html , you may notice that the entire contents of plotly.js have also been embedded. This will be true for all output created by Plotly for Rust's .to_html() function. This also means that if we have two of these plots in our notebook using the workaround, we will have two copies of plotly.js also embedded. Because we're using the Plotly Jupyter Lab extension, @jupyterlab/plotly-extension , we don't need to embed plotly.js at all.

So let's extract the part of this HTML file that we actually need. We can do this by slicing out a substring starting from one part of the string that we know starts off the part we need, <div id=\"plotly-html-element\" class=\"plotly-graph-div

In [12]:

let start_bytes = plotly_contents
    .find("<div id=\"plotly-html-element\" class=\"plotly-graph-div\"")
    .unwrap_or(0);

and ending at another part that we know immediately follows the last part we need </div></body></html> .

In [13]:

let end_bytes = plotly_contents
    .find("\n</div>\n</body>\n</html>")
    .unwrap_or(plotly_contents.len());

Let's print out our substring to see what we've ended up with.

In [6]:

&plotly_contents[start_bytes..end_bytes]

Out[6]:

"<div id=\"plotly-html-element\" class=\"plotly-graph-div\" style=\"height:100%; width:100%;\"></div>\n    <div ><img id=\"image-export\" class=\"plotly-graph-div\" hidden></img></div>\n    <script type=\"text/javascript\">\n                \n                window.PLOTLYENV=window.PLOTLYENV || {};                    \n                if (document.getElementById(\"plotly-html-element\")) {\n\n                    var d3 = Plotly.d3;\n                    var image_element= d3.select(\'#image-export\');\n\n                    var trace_0 = {\"type\":\"scatter\",\"x\":[1,2,3,4],\"y\":[10,15,13,17],\"name\":\"trace1\",\"mode\":\"markers\"};\nvar trace_1 = {\"type\":\"scatter\",\"x\":[2,3,4,5],\"y\":[16,5,11,9],\"name\":\"trace2\",\"mode\":\"lines\"};\nvar trace_2 = {\"type\":\"scatter\",\"x\":[1,2,3,4],\"y\":[12,9,15,12],\"name\":\"trace3\"};\n\nvar data = [trace_0,trace_1,trace_2];\nvar layout = {};\n\n\n                    Plotly.newPlot(\'plotly-html-element\', data, layout,\n                        {\"responsive\": true})\n                        .then(\n                            function(gd) {\n                              Plotly.toImage(gd,{height:0,width:0})\n                                 .then(\n                                     function(url) {\n                                         if(false) {\n                                             image_element.attr(\"src\", url);\n                                             return Plotly.toImage(gd,{format:\'\',height:0,width:0});\n                                         }\n                                    })\n                            });\n\n                };\n\n\n    </script>"

This now looks to be dramatically smaller in file size.

Allowing Multiple Plots

However, you may have noticed a clue as to why we can only properly output a single Plotly plot per notebook. This is because of <div id=\"plotly-html-element\" , meaning that every plot will have the same ID. In the Python version of Plotly, each plot has a randomly generated ID, so let's do the same using nanoid .

In [7]:

nanoid!()

Out[7]:

"lHwIxvSKjH6GcCRsFbB_1"

If we replace every occurrence of the original ID, plotly-html-element , with a new one generated by nanoid , then we should be able to output multiple plots.

In [8]:

&plotly_contents[start_bytes..end_bytes]
        .replace("plotly-html-element", Box::leak(nanoid!().into_boxed_str()))

Out[8]:

"<div id=\"epHGixQbQByA7OhF9EqX5\" class=\"plotly-graph-div\" style=\"height:100%; width:100%;\"></div>\n    <div ><img id=\"image-export\" class=\"plotly-graph-div\" hidden></img></div>\n    <script type=\"text/javascript\">\n                \n                window.PLOTLYENV=window.PLOTLYENV || {};                    \n                if (document.getElementById(\"epHGixQbQByA7OhF9EqX5\")) {\n\n                    var d3 = Plotly.d3;\n                    var image_element= d3.select(\'#image-export\');\n\n                    var trace_0 = {\"type\":\"scatter\",\"x\":[1,2,3,4],\"y\":[10,15,13,17],\"name\":\"trace1\",\"mode\":\"markers\"};\nvar trace_1 = {\"type\":\"scatter\",\"x\":[2,3,4,5],\"y\":[16,5,11,9],\"name\":\"trace2\",\"mode\":\"lines\"};\nvar trace_2 = {\"type\":\"scatter\",\"x\":[1,2,3,4],\"y\":[12,9,15,12],\"name\":\"trace3\"};\n\nvar data = [trace_0,trace_1,trace_2];\nvar layout = {};\n\n\n                    Plotly.newPlot(\'epHGixQbQByA7OhF9EqX5\', data, layout,\n                        {\"responsive\": true})\n                        .then(\n                            function(gd) {\n                              Plotly.toImage(gd,{height:0,width:0})\n                                 .then(\n                                     function(url) {\n                                         if(false) {\n                                             image_element.attr(\"src\", url);\n                                             return Plotly.toImage(gd,{format:\'\',height:0,width:0});\n                                         }\n                                    })\n                            });\n\n                };\n\n\n    </script>"

Putting Everything Together

Let's put everything together and demonstrate our ability to output multiple plots.

The following will be the first plot.

In [9]:

println!("EVCXR_BEGIN_CONTENT text/html\n{}\nEVCXR_END_CONTENT",
    format!("<div>{}</div>",
        &plotly_contents[start_bytes..end_bytes]
        .replace("plotly-html-element", Box::leak(nanoid!().into_boxed_str()))));

Out[9]:

The following will be the second plot.

In [10]:

println!("EVCXR_BEGIN_CONTENT text/html\n{}\nEVCXR_END_CONTENT",
    format!("<div>{}</div>",
        &plotly_contents[start_bytes..end_bytes]
        .replace("plotly-html-element", Box::leak(nanoid!().into_boxed_str()))));

Out[10]:

We can now see two plots, with this notebook currently weighing in at a file size of only $16$ KB. We can also see that I have surrounded the HTML for our ploty with a <div> , this was needed to ensure the full plot is visible in a notebook cell.

Finally, let's clean up by deleting our temporary HTML file.

In [11]:

fs::remove_file(plotly_file)?;

In this section, we've improved our workaround for data visualisation with Plotly for Rust in Jupyter notebooks. We achieved this by stripping out excess JavaScript to reduce the file size and generating random IDs to allow multiple plots. In the next section, we'll implement all of this into a single function so that we can visualise our data easily in the upcoming sections.


以上所述就是小编给大家介绍的《Better Plotting with Plotly》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

不是为了快乐

不是为了快乐

宗萨蒋扬钦哲仁波切 / 姚仁喜 / 深圳报业集团出版社 / 2013-1 / 38.00元

前行修持是一套完整的实修系统,它既是一切佛法修持的根基,又囊括了所有修持的精华,以及心灵之道上所需的一切;既适合入门者打造学佛基本功,也是修行人需要终生修持的心法。书中除了实际的方法指导之外,还不断启发佛法的珍贵与修持的必要,并处处可见对学佛者的鼓舞和纠正,其最终的用心,是让我们踏上不间断的修持之路,真正转化我们僵硬、散乱和困惑的心。 在现代人看来,快乐,理应是最值得追求的目标。我们希望生活......一起来看看 《不是为了快乐》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

html转js在线工具
html转js在线工具

html转js在线工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具