Finishing Touches for Visualisation

Preamble

In [2]:
extern crate plotly;
extern crate nanoid;
extern crate darn;

use plotly::{Plot, Scatter, Layout};
use plotly::common::{Mode, Anchor, Orientation, Title};
use plotly::layout::{Legend, Margin, Axis};
use nanoid::nanoid;
use std::fs;

Plotly Workaround Function

In the last section, we improved upon our Plotly workaround to get our plots to appear within our notebooks. All that's left now is to separate our workaround into a function so that we can re-use it throughout the rest of this book. We'll name this function show_plot()

In [3]:
fn show_plot(plot: Plot) { 
    let plotly_file = "temp_plot.html";
    plot.to_html(plotly_file);
    let plotly_contents = fs::read_to_string(plotly_file).unwrap();
    fs::remove_file(plotly_file);

    let start_bytes = plotly_contents
        .find("<div id=\"plotly-html-element\" class=\"plotly-graph-div\"")
        .unwrap_or(0);
    
    let end_bytes = plotly_contents
        .find("\n</div>\n</body>\n</html>")
        .unwrap_or(plotly_contents.len());
    
    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()))
        .replace("window.PLOTLYENV=",
                 "require([\"plotly\"], function(Plotly) { window.PLOTLYENV=")
        .replace("};\n\n\n    </script>","};\n\n\n});    </script>")));
}

Now let's use the same example code from the previous sections and use our function above to display the plot. This time, we're going to use the Layout struct and specify some customisations. This will reduce the padding on our plot, change the positioning of the legend, and label the axes. This is not a necessary step, however, the output should look much nicer.

In [4]:
let layout = Layout::new()
    .xaxis(Axis::new().title(Title::new("x axis")))
    .yaxis(Axis::new().title(Title::new("y axis")))
    .margin(Margin::new().top(0).bottom(40).left(40).right(10))
    .legend(Legend::new().x(0.5).y(1.1)
    .orientation(Orientation::Horizontal).x_anchor(Anchor::Center));

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.set_layout(layout);
plot.add_trace(trace1);
plot.add_trace(trace2);
plot.add_trace(trace3);

To display our plot, we can pass the plot variable to our show_plot() function.

In [5]:
show_plot(plot);
Out[5]:

The DARN Crate

To make things even easier throughout this book, I've created a crate, darn (Data Analysis with Rust Notebooks), and published it on the Rust Package Registry. All we need to do now is use extern crate darn; to get this function, which has a little extra to make the plots look even nicer with some layout defaults. Let's use the same example code, this time noting that we are specifying less layout information.

In [6]:
let layout = Layout::new()
    .xaxis(Axis::new().title(Title::new("x axis")))
    .yaxis(Axis::new().title(Title::new("y axis")));

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.set_layout(layout);
plot.add_trace(trace1);
plot.add_trace(trace2);
plot.add_trace(trace3);

This time, we'll use the function provided by our crate, darn::show_plot(), to display our plot.

In [7]:
darn::show_plot(plot);

Conclusion

In this section, we took our Plotly workaround a step further to its final destination. Our Plotly workaround is now available as part of the darn crate and ready to use in the following sections.

Support this work

You can access this notebook and more by getting the e-book on Data Analysis with Rust Notebooks.