Plotly.rs

Plotly.rs is a plotting library powered by Plotly.js. The aim is to bring over to Rust all the functionality that Python users have come to rely on with the added benefit of type safety and speed.

Plotly.rs is free and open source. You can find the source on GitHub. Issues and feature requests can be posted on the issue tracker.

API Docs

This book is intended to be a recipe index, which closely follows the plotly.js examples, and is complemented by the API documentation.

Contributing

Contributions are always welcomed, no matter how large or small. Refer to the contributing guidelines for further pointers, and, if in doubt, open an issue.

License

Plotly.rs is distributed under the terms of the MIT license.

See LICENSE

Getting Started

To start using plotly.rs in your project add the following to your Cargo.toml:

[dependencies]
plotly = "0.11"

Plotly.rs is ultimately a thin wrapper around the plotly.js library. The main job of this library is to provide structs and enums which get serialized to json and passed to the plotly.js library to actually do the heavy lifting. As such, if you are familiar with plotly.js or its derivatives (e.g. the equivalent Python library), then you should find plotly.rs intuitive to use.

A Plot struct contains one or more Trace objects which describe the structure of data to be displayed. Optional Layout and Configuration structs can be used to specify the layout and config of the plot, respectively.

The builder pattern is used extensively throughout the library, which means you only need to specify the attributes and details you desire. Any attributes that are not set will fall back to the default value used by plotly.js.

All available traces (e.g. Scatter, Bar, Histogram, etc), the Layout, Configuration and Plot have been hoisted in the plotly namespace so that they can be imported simply using the following:

#![allow(unused)]
fn main() {
use plotly::{Plot, Layout, Scatter};
}

The aforementioned components can be combined to produce as simple plot as follows:

use plotly::common::Mode;
use plotly::{Plot, Scatter};

fn line_and_scatter_plot() {
    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.show();
}

fn main() -> std::io::Result<()> {
    line_and_scatter_plot();
    Ok(())
}

which results in the following figure (displayed here as a static png file):

line_and_scatter_plot

The above code will generate an interactive html page of the Plot and display it in the default browser. The html for the plot is stored in the platform specific temporary directory. To save the html result, you can do so quite simply:

#![allow(unused)]
fn main() {
plot.write_html("/home/user/line_and_scatter_plot.html");
}

It is often the case that plots are produced to be included in a document and a different format for the plot is desirable (e.g. png, jpeg, etc). Given that the html version of the plot is composed of vector graphics, the display when converted to a non-vector format (e.g. png) is not guaranteed to be identical to the one displayed in html. This means that some fine tuning may be required to get to the desired output. To support that iterative workflow, Plot has a show_image() method which will display the rasterised output to the target format, for example:

#![allow(unused)]
fn main() {
plot.show_image(ImageFormat::PNG, 1280, 900);
}

will display in the browser the rasterised plot; 1280 pixels wide and 900 pixels tall, in png format.

Once a satisfactory result is achieved, and assuming the kaleido feature is enabled, the plot can be saved using the following:

#![allow(unused)]
fn main() {
plot.write_image("/home/user/plot_name.ext", ImageFormat::PNG, 1280, 900, 1.0);
}

The extension in the file-name path is optional as the appropriate extension (ImageFormat::PNG) will be included. Note that in all functions that save files to disk, both relative and absolute paths are supported.

Saving Plots

To add the ability to save plots in the following formats: png, jpeg, webp, svg, pdf and eps, you can use the kaleido feature. This feature depends on plotly/Kaleido: a cross-platform open source library for generating static images. All the necessary binaries have been included with plotly_kaleido for Linux, Windows and MacOS. Previous versions of plotly.rs used the orca feature, however, this has been deprecated as it provided the same functionality but required additional installation steps. To enable the kaleido feature add the following to your Cargo.toml:

[dependencies]
plotly = { version = "0.11", features = ["kaleido"] }

WebAssembly Support

As of v0.8.0, plotly.rs can now be used in a Wasm environment by enabling the wasm feature in your Cargo.toml:

[dependencies]
plotly = { version = ">=0.8.0" features = ["wasm"] }

The wasm feature exposes rudimentary bindings to the plotly.js library, which can then be used in a wasm environment such as the Yew frontend framework.

To make a very simple Plot component might look something like:

#![allow(unused)]
fn main() {
use yew::prelude::*;

#[derive(Properties, PartialEq)]
pub struct PlotProps {
    pub id: String,
    pub plot: plotly::Plot,
    pub class: Option<Classes>,
}

#[function_component(Plot)]
pub fn plot(props: &PlotProps) -> Html {
    let PlotProps { id, plot, class } = props;

    let p = yew_hooks::use_async::<_, _, ()>({
        let id = id.clone();
        let plot = plot.clone();
        async move {
            plotly::bindings::new_plot(&id, &plot).await;
            Ok(())
        }
    });

    {
        let id = id.clone();
        let plot = plot.clone();
        use_effect_with_deps(
            move |(_, _)| {
                p.run();
                || ()
            },
            (id, plot),
        );
    }

    html! {
        <div id={id.clone()} class={class.clone()}></div>
    }
}
}

Fundamentals

Functionality that applies to the library as a whole is described in the next sections.

Jupyter Support

As of version 0.7.0, Plotly.rs has native support for the EvCxR Jupyter Kernel.

Once you've installed the required packages you'll be able to run all the examples shown here as well as all the recipes in Jupyter Lab!

Installation

It is assumed that an installation of the Anaconda Python distribution is already present in the system. If that is not the case you can follow these instructions to get up and running with Anaconda.

conda install -c plotly plotly=4.9.0
conda install jupyterlab "ipywidgets=7.5"

optionally (or instead of jupyterlab) you can also install Jupyter Notebook:

conda install notebook

Although there are alternative methods to enable support for the EvCxR Jupyter Kernel, we have elected to keep the requirements consistent with what those of other languages, e.g. Julia, Python and R. This way users know what to expect; and also the folks at Plotly have done already most of the heavy lifting to create an extension for Jupyter Lab that works very well.

Run the following to install the Plotly Jupyter Lab extension:

jupyter labextension install jupyterlab-plotly@4.9.0

Once this step is complete to make sure the installation so far was successful, run the following command:

jupyter lab

Open a Python 3 kernel copy/paste the following code in a cell and run it:

import plotly.graph_objects as go
fig = go.Figure(data=go.Bar(x=['a', 'b', 'c'], y=[11, 22, 33]))
fig.show()

You should see the following figure:

Next you need to install the EvCxR Jupyter Kernel. Note that EvCxR requires CMake as it has to compile ZMQ. If CMake is already installed on your system and is in your path (to test that simply run cmake --version if that returns a version you're good to go) then continue to the next steps.

In a command line execute the following commands:

cargo install evcxr_jupyter
evcxr_jupyter --install

If you're not familiar with the EvCxR kernel it would be good that you at least glance over the EvCxR Jupyter Tour.

Usage

Launch Jupyter Lab:

jupyter lab

create a new notebook and select the Rust kernel. Then create the following three cells and execute them in order:

:dep ndarray = "0.15.6"
:dep plotly = { version = ">=0.7.0" }
#![allow(unused)]
fn main() {
extern crate ndarray;
extern crate plotly;
extern crate rand_distr;
}
#![allow(unused)]
fn main() {
use ndarray::Array;
use plotly::common::Mode;
use plotly::layout::{Layout};
use plotly::{Plot, Scatter};
use rand_distr::{num_traits::Float, Distribution};
}

Now we're ready to start plotting!

#![allow(unused)]
fn main() {
let x0 = Array::linspace(1.0, 3.0, 200).into_raw_vec();
let y0 = x0.iter().map(|v| *v * (v.powf(2.)).sin() + 1.).collect();

let trace = Scatter::new(x0, y0);
let mut plot = Plot::new();
plot.add_trace(trace);

let layout = Layout::new().height(525);
plot.set_layout(layout);

plot.lab_display();
format!("EVCXR_BEGIN_CONTENT application/vnd.plotly.v1+json\n{}\nEVCXR_END_CONTENT", plot.to_json())
}

For Jupyter Lab there are two ways to display a plot in the EvCxR kernel, either have the plot object be in the last line without a semicolon or directly invoke the Plot::lab_display method on it; both have the same result. You can also find an example notebook here that will periodically be updated with examples.

The process for Jupyter Notebook is very much the same with one exception; the Plot::notebook_display method must be used to display the plot. You can find an example notebook here

ndarray Support

To enable ndarray support in Plotly.rs add the following feature to your Cargo.toml file:

[dependencies]
plotly = { version = ">=0.7.0", features = ["plotly_ndarray"] }

This extends the Plotly.rs API in two ways:

  • Scatter traces can now be created using the Scatter::from_ndarray constructor,
  • and also multiple traces can be created with the Scatter::to_traces method.

The full source code for the examples below can be found here.

ndarray Traces

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use plotly::common::{Mode};
use plotly::{Plot, Scatter};
use ndarray::{Array, Ix1, Ix2};
use plotly::ndarray::ArrayTraces;
}

Single Trace

#![allow(unused)]
fn main() {
fn single_ndarray_trace(show: bool) {
    let n: usize = 11;
    let t: Array<f64, Ix1> = Array::range(0., 10., 10. / n as f64);
    let ys: Array<f64, Ix1> = t.iter().map(|v| (*v).powf(2.)).collect();

    let trace = Scatter::from_array(t, ys).mode(Mode::LinesMarkers);

    let mut plot = Plot::new();
    plot.add_trace(trace);
    if show {
        plot.show();
    }
    println!("{}", plot.to_inline_html(Some("single_ndarray_trace")));
}
}

Multiple Traces

To display a 2D array (Array<_, Ix2>) you can use the Scatter::to_traces method. The first argument of the method represents the common axis for the traces (x axis) whilst the second argument contains a collection of traces. At this point it should be noted that there is some ambiguity when passing a 2D array; namely are the traces arranged along the columns or the rows of the matrix? This ambiguity is resolved by the third argument of the Scatter::to_traces method. If that argument is set to ArrayTraces::OverColumns then the library assumes that every column represents an individual trace, alternatively if this is set to ArrayTraces::OverRows the assumption is that every row represents a trace.

To illustrate this distinction consider the following examples:

#![allow(unused)]
fn main() {
fn multiple_ndarray_traces_over_columns(show: bool) {
    let n: usize = 11;
    let t: Array<f64, Ix1> = Array::range(0., 10., 10. / n as f64);
    let mut ys: Array<f64, Ix2> = Array::zeros((11, 11));
    let mut count = 0.;
    for mut row in ys.columns_mut() {
        for index in 0..row.len() {
            row[index] = count + (index as f64).powf(2.);
        }
        count += 1.;
    }

    let traces =
        Scatter::default()
            .mode(Mode::LinesMarkers)
            .to_traces(t, ys, ArrayTraces::OverColumns);

    let mut plot = Plot::new();
    plot.add_traces(traces);
    if show {
        plot.show();
    }
    println!("{}", plot.to_inline_html(Some("multiple_ndarray_traces_over_columns")));
}
}

Replacing ArrayTraces::OverColumns with ArrayTraces::OverRows results in the following:

Shapes

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use ndarray::Array;
use plotly::common::{
    Fill, Font, Mode,
};
use plotly::layout::{
    Axis, GridPattern, Layout, LayoutGrid, Margin, Shape, ShapeLayer, ShapeLine,
    ShapeType,
};
use plotly::{Bar, color::NamedColor, Plot, Scatter};
use rand::thread_rng;
use rand_distr::{Distribution, Normal};
}

The to_inline_html method is used to produce the html plot displayed in this page.

Filled Area Chart

#![allow(unused)]
fn main() {
fn filled_area_chart(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![0, 1, 2, 0], vec![0, 2, 0, 0]).fill(Fill::ToSelf);
    let trace2 =
        Scatter::new(vec![3, 3, 5, 5, 3], vec![0.5, 1.5, 1.5, 0.5, 0.5]).fill(Fill::ToSelf);

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    if show {
        plot.show();
    }
    plot
}
}

Vertical and Horizontal Lines Positioned Relative to Axes

#![allow(unused)]
fn main() {
fn vertical_and_horizontal_lines_positioned_relative_to_axes(show: bool) -> Plot {
    let trace = Scatter::new(vec![2.0, 3.5, 6.0], vec![1.0, 1.5, 1.0])
        .text_array(vec![
            "Vertical Line",
            "Horizontal Dashed Line",
            "Diagonal dotted Line",
        ])
        .mode(Mode::Text);

    let mut plot = Plot::new();
    plot.add_trace(trace);

    let mut layout = Layout::new()
        .x_axis(Axis::new().range(vec![0.0, 7.0]))
        .y_axis(Axis::new().range(vec![0.0, 2.5]));

    layout.add_shape(
        Shape::new()
            .shape_type(ShapeType::Line)
            .x0(1)
            .y0(0)
            .x1(1)
            .y1(2)
            .line(ShapeLine::new().color(NamedColor::RoyalBlue).width(3.)),
    );

    layout.add_shape(
        Shape::new()
            .shape_type(ShapeType::Line)
            .x0(2)
            .y0(2)
            .x1(5)
            .y1(2)
            .line(
                ShapeLine::new()
                    .color(NamedColor::LightSeaGreen)
                    .width(3.)
                    .dash(DashType::DashDot),
            ),
    );

    layout.add_shape(
        Shape::new()
            .shape_type(ShapeType::Line)
            .x0(4)
            .y0(0)
            .x1(6)
            .y1(2)
            .line(
                ShapeLine::new()
                    .color(NamedColor::MediumPurple)
                    .width(3.)
                    .dash(DashType::Dot),
            ),
    );

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Lines Positioned Relative to the Plot and to the Axes

#![allow(unused)]
fn main() {
fn lines_positioned_relative_to_the_plot_and_to_the_axes(show: bool) -> Plot {
    let trace = Scatter::new(vec![2.0, 6.0], vec![1.0, 1.0])
        .text_array(vec![
            "Line positioned relative to the plot",
            "Line positioned relative to the axes",
        ])
        .mode(Mode::Text);

    let mut plot = Plot::new();
    plot.add_trace(trace);

    let mut layout = Layout::new()
        .x_axis(Axis::new().range(vec![0.0, 8.0]))
        .y_axis(Axis::new().range(vec![0.0, 2.]));

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Line)
            .x0(4)
            .y0(0)
            .x1(8)
            .y1(1)
            .line(ShapeLine::new().color(NamedColor::LightSeaGreen).width(3.)),
    );
    layout.add_shape(
        Shape::new()
            .x_ref("paper")
            .y_ref("paper")
            .shape_type(ShapeType::Line)
            .x0(0.0)
            .y0(0.0)
            .x1(0.5)
            .y1(0.5)
            .line(ShapeLine::new().color(NamedColor::DarkOrange).width(3.)),
    );

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Creating Tangent Lines with Shapes

#![allow(unused)]
fn main() {
fn creating_tangent_lines_with_shapes(show: bool) -> Plot {
    let x0 = Array::linspace(1.0, 3.0, 200).into_raw_vec_and_offset().0;
    let y0 = x0.iter().map(|v| *v * (v.powf(2.)).sin() + 1.).collect();

    let trace = Scatter::new(x0, y0);
    let mut plot = Plot::new();
    plot.add_trace(trace);

    let mut layout =
        Layout::new().title("$f(x)=x\\sin(x^2)+1\\\\ f\'(x)=\\sin(x^2)+2x^2\\cos(x^2)$");

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .opacity(0.7)
            .shape_type(ShapeType::Line)
            .x0(1.)
            .y0(2.30756)
            .x1(1.75)
            .y1(2.30756)
            .line(ShapeLine::new().color(NamedColor::Crimson).width(2.5)),
    );

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .opacity(0.7)
            .shape_type(ShapeType::Line)
            .x0(2.5)
            .y0(3.80796)
            .x1(3.05)
            .y1(3.80796)
            .line(ShapeLine::new().color(NamedColor::Crimson).width(2.5)),
    );

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .opacity(0.7)
            .shape_type(ShapeType::Line)
            .x0(1.90)
            .y0(-1.1827)
            .x1(2.5)
            .y1(-1.1827)
            .line(ShapeLine::new().color(NamedColor::Crimson).width(2.5)),
    );

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Rectangles Positioned Relative to the Axes

#![allow(unused)]
fn main() {
fn rectangles_positioned_relative_to_the_axes(show: bool) -> Plot {
    let trace = Scatter::new(vec![1.5, 4.5], vec![0.75, 0.75])
        .text_array(vec!["Unfilled Rectangle", "Filled Rectangle"])
        .mode(Mode::Text);
    let mut plot = Plot::new();
    plot.add_trace(trace);

    let mut layout = Layout::new()
        .x_axis(Axis::new().range(vec![0.0, 7.0]).show_grid(false))
        .y_axis(Axis::new().range(vec![0.0, 3.5]));

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Rect)
            .x0(1.)
            .y0(1.)
            .x1(2.)
            .y1(3.)
            .line(ShapeLine::new().color(NamedColor::RoyalBlue)),
    );

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Rect)
            .x0(3.)
            .y0(1.)
            .x1(6.)
            .y1(2.)
            .line(ShapeLine::new().color(NamedColor::RoyalBlue).width(2.))
            .fill_color(NamedColor::LightSkyBlue),
    );

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Rectangle Positioned Relative to the Plot and to the Axes

#![allow(unused)]
fn main() {
fn rectangle_positioned_relative_to_the_plot_and_to_the_axes(show: bool) -> Plot {
    let trace = Scatter::new(vec![1.5, 3.], vec![2.5, 2.5])
        .text_array(vec![
            "Rectangle reference to the plot",
            "Rectangle reference to the axes",
        ])
        .mode(Mode::Text);

    let mut plot = Plot::new();
    plot.add_trace(trace);

    let mut layout = Layout::new()
        .x_axis(Axis::new().range(vec![0.0, 4.0]).show_grid(false))
        .y_axis(Axis::new().range(vec![0.0, 4.0]));

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Rect)
            .x0(2.5)
            .y0(0.0)
            .x1(3.5)
            .y1(2.0)
            .line(ShapeLine::new().color(NamedColor::RoyalBlue).width(3.))
            .fill_color(NamedColor::LightSkyBlue),
    );

    layout.add_shape(
        Shape::new()
            .x_ref("paper")
            .y_ref("paper")
            .shape_type(ShapeType::Rect)
            .x0(0.25)
            .y0(0.0)
            .x1(0.5)
            .y1(0.5)
            .line(ShapeLine::new().color(NamedColor::LightSeaGreen).width(3.))
            .fill_color(NamedColor::PaleTurquoise),
    );

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Highlighting Time Series Regions with Rectangle Shapes

#![allow(unused)]
fn main() {
fn highlighting_time_series_regions_with_rectangle_shapes(show: bool) -> Plot {
    let x = vec![
        "2015-02-01",
        "2015-02-02",
        "2015-02-03",
        "2015-02-04",
        "2015-02-05",
        "2015-02-06",
        "2015-02-07",
        "2015-02-08",
        "2015-02-09",
        "2015-02-10",
        "2015-02-11",
        "2015-02-12",
        "2015-02-13",
        "2015-02-14",
        "2015-02-15",
        "2015-02-16",
        "2015-02-17",
        "2015-02-18",
        "2015-02-19",
        "2015-02-20",
        "2015-02-21",
        "2015-02-22",
        "2015-02-23",
        "2015-02-24",
        "2015-02-25",
        "2015-02-26",
        "2015-02-27",
        "2015-02-28",
    ];
    let y = vec![
        -14, -17, -8, -4, -7, -10, -12, -14, -12, -7, -11, -7, -18, -14, -14, -16, -13, -7, -8,
        -14, -8, -3, -9, -9, -4, -13, -9, -6,
    ];

    let trace = Scatter::new(x, y).mode(Mode::Lines).name("temperature");
    let mut plot = Plot::new();
    plot.add_trace(trace);

    let mut layout = Layout::new();

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("paper")
            .shape_type(ShapeType::Rect)
            .x0("2015-02-04")
            .y0(0)
            .x1("2015-02-06")
            .y1(1)
            .fill_color(NamedColor::LightSalmon)
            .opacity(0.5)
            .layer(ShapeLayer::Below)
            .line(ShapeLine::new().width(0.)),
    );

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("paper")
            .shape_type(ShapeType::Rect)
            .x0("2015-02-20")
            .y0(0)
            .x1("2015-02-22")
            .y1(1)
            .fill_color(NamedColor::LightSalmon)
            .opacity(0.5)
            .layer(ShapeLayer::Below)
            .line(ShapeLine::new().width(0.)),
    );

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Circles Positioned Relative to the Axes

#![allow(unused)]
fn main() {
fn circles_positioned_relative_to_the_axes(show: bool) -> Plot {
    let trace = Scatter::new(vec![1.5, 3.5], vec![0.75, 2.5])
        .text_array(vec!["Unfilled Circle", "Filled Circle"])
        .mode(Mode::Text);

    let mut plot = Plot::new();
    plot.add_trace(trace);

    let mut layout = Layout::new()
        .x_axis(Axis::new().range(vec![0.0, 4.5]).zero_line(false))
        .y_axis(Axis::new().range(vec![0.0, 4.5]))
        .width(800)
        .height(800);

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Circle)
            .x0(1)
            .y0(1)
            .x1(3)
            .y1(3)
            .line(ShapeLine::new().color(NamedColor::LightSeaGreen)),
    );

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Circle)
            .x0(3)
            .y0(3)
            .x1(4)
            .y1(4)
            .line(ShapeLine::new().color(NamedColor::LightSeaGreen))
            .fill_color(NamedColor::PaleTurquoise),
    );

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Highlighting Clusters of Scatter Points with Circle Shapes

#![allow(unused)]
fn main() {
fn highlighting_clusters_of_scatter_points_with_circle_shapes(show: bool) -> Plot {
    let mut rng = thread_rng();
    let x0 = Normal::new(2., 0.45)
        .unwrap()
        .sample_iter(&mut rng)
        .take(300)
        .collect::<Vec<f64>>();
    let y0 = Normal::new(2., 0.45)
        .unwrap()
        .sample_iter(&mut rng)
        .take(300)
        .collect::<Vec<f64>>();
    let x1 = Normal::new(6., 0.4)
        .unwrap()
        .sample_iter(&mut rng)
        .take(300)
        .collect::<Vec<f64>>();
    let y1 = Normal::new(6., 0.4)
        .unwrap()
        .sample_iter(&mut rng)
        .take(300)
        .collect::<Vec<f64>>();
    let x2 = Normal::new(4., 0.3)
        .unwrap()
        .sample_iter(&mut rng)
        .take(300)
        .collect::<Vec<f64>>();
    let y2 = Normal::new(4., 0.3)
        .unwrap()
        .sample_iter(&mut rng)
        .take(300)
        .collect::<Vec<f64>>();

    let x0min = x0.iter().copied().fold(f64::NAN, f64::min);
    let x0max = x0.iter().copied().fold(f64::NAN, f64::max);
    let y0min = y0.iter().copied().fold(f64::NAN, f64::min);
    let y0max = y0.iter().copied().fold(f64::NAN, f64::max);

    let x1min = x1.iter().copied().fold(f64::NAN, f64::min);
    let x1max = x1.iter().copied().fold(f64::NAN, f64::max);
    let y1min = y1.iter().copied().fold(f64::NAN, f64::min);

    let x2min = x2.iter().copied().fold(f64::NAN, f64::min);
    let x2max = x2.iter().copied().fold(f64::NAN, f64::max);
    let y2min = y2.iter().copied().fold(f64::NAN, f64::min);

    let mut plot = Plot::new();
    plot.add_trace(Scatter::new(x0, y0.clone()).mode(Mode::Markers));
    plot.add_trace(Scatter::new(x1.clone(), y1).mode(Mode::Markers));
    plot.add_trace(Scatter::new(x2, y2).mode(Mode::Markers));
    plot.add_trace(Scatter::new(x1, y0).mode(Mode::Markers));

    let mut layout = Layout::new().show_legend(false);

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Circle)
            .x0(x0min)
            .y0(y0min)
            .x1(x0max)
            .y1(y0max)
            .opacity(0.2)
            .fill_color(NamedColor::Blue)
            .line(ShapeLine::new().color(NamedColor::Blue)),
    );
    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Circle)
            .x0(x1min)
            .y0(y1min)
            .x1(x1max)
            .y1(x1max)
            .opacity(0.2)
            .fill_color(NamedColor::Orange)
            .line(ShapeLine::new().color(NamedColor::Orange)),
    );
    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Circle)
            .x0(x2min)
            .y0(y2min)
            .x1(x2max)
            .y1(x2max)
            .opacity(0.2)
            .fill_color(NamedColor::Green)
            .line(ShapeLine::new().color(NamedColor::Green)),
    );
    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Circle)
            .x0(x1min)
            .y0(y0min)
            .x1(x1max)
            .y1(x0max)
            .opacity(0.2)
            .fill_color(NamedColor::Red)
            .line(ShapeLine::new().color(NamedColor::Red)),
    );

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Venn Diagram with Circle Shapes

#![allow(unused)]
fn main() {
fn venn_diagram_with_circle_shapes(show: bool) -> Plot {
    let mut plot = Plot::new();
    plot.add_trace(
        Scatter::new(vec![1., 1.75, 2.5], vec![1., 1., 1.])
            .text_array(vec!["$A$", "$A+B$", "$B$"])
            .mode(Mode::Text)
            .text_font(
                Font::new()
                    .color(NamedColor::Black)
                    .size(18)
                    .family("Arial"),
            ),
    );

    let mut layout = Layout::new()
        .x_axis(
            Axis::new()
                .zero_line(false)
                .show_grid(false)
                .show_tick_labels(false),
        )
        .y_axis(
            Axis::new()
                .zero_line(false)
                .show_grid(false)
                .show_tick_labels(false),
        )
        .margin(Margin::new().left(20).right(20).bottom(100))
        .height(600)
        .width(800)
        .plot_background_color(NamedColor::White);

    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Circle)
            .x0(0)
            .y0(0)
            .x1(2)
            .y1(2)
            .opacity(0.3)
            .layer(ShapeLayer::Below)
            .fill_color(NamedColor::Blue)
            .line(ShapeLine::new().color(NamedColor::Blue)),
    );
    layout.add_shape(
        Shape::new()
            .x_ref("x")
            .y_ref("y")
            .shape_type(ShapeType::Circle)
            .x0(1.5)
            .y0(0.)
            .x1(3.5)
            .y1(2.)
            .opacity(0.3)
            .layer(ShapeLayer::Below)
            .fill_color(NamedColor::Gray)
            .line(ShapeLine::new().color(NamedColor::Gray)),
    );

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Adding Shapes to Subplots

#![allow(unused)]
fn main() {
fn adding_shapes_to_subplots(show: bool) -> Plot {
    let mut plot = Plot::new();
    plot.add_trace(
        Scatter::new(vec![2, 6], vec![1, 1])
            .x_axis("x1")
            .y_axis("y1"),
    );
    plot.add_trace(
        Bar::new(vec![1, 2, 3], vec![4, 5, 6])
            .x_axis("x2")
            .y_axis("y2"),
    );
    plot.add_trace(
        Scatter::new(vec![10, 20], vec![40, 50])
            .x_axis("x3")
            .y_axis("y3"),
    );
    plot.add_trace(
        Bar::new(vec![11, 13, 15], vec![8, 11, 20])
            .x_axis("x4")
            .y_axis("y4"),
    );

    let mut layout = Layout::new()
        .grid(
            LayoutGrid::new()
                .rows(2)
                .columns(2)
                .pattern(GridPattern::Independent),
        )
        .x_axis(Axis::new().domain(&[0.0, 0.48]).anchor("x1"))
        .y_axis(Axis::new().domain(&[0.52, 1.]).anchor("y1"))
        .x_axis2(Axis::new().domain(&[0.52, 1.0]).anchor("x2"))
        .y_axis2(Axis::new().domain(&[0.5, 1.]).anchor("y2"))
        .x_axis3(Axis::new().domain(&[0.0, 0.48]).anchor("x3"))
        .y_axis3(Axis::new().domain(&[0.0, 0.48]).anchor("y3"))
        .x_axis4(Axis::new().domain(&[0.52, 1.0]).anchor("x4"))
        .y_axis4(Axis::new().domain(&[0.0, 0.48]).anchor("y4"));

    layout.add_shape(
        Shape::new()
            .x_ref("x1")
            .y_ref("y1")
            .shape_type(ShapeType::Line)
            .x0(3)
            .y0(0.5)
            .x1(5)
            .y1(0.8)
            .line(ShapeLine::new().width(3.)),
    );
    layout.add_shape(
        Shape::new()
            .x_ref("x2")
            .y_ref("y2")
            .shape_type(ShapeType::Rect)
            .x0(4)
            .y0(2)
            .x1(5)
            .y1(6),
    );
    layout.add_shape(
        Shape::new()
            .x_ref("x3")
            .y_ref("y3")
            .shape_type(ShapeType::Rect)
            .x0(10)
            .y0(20)
            .x1(15)
            .y1(30),
    );
    layout.add_shape(
        Shape::new()
            .x_ref("x4")
            .y_ref("y4")
            .shape_type(ShapeType::Circle)
            .x0(5)
            .y0(12)
            .x1(10)
            .y1(18),
    );

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

SVG Paths

#![allow(unused)]
fn main() {
fn svg_paths(show: bool) -> Plot {
    let mut plot = Plot::new();
    plot.add_trace(
        Scatter::new(vec![2, 1, 8, 8], vec![0.25, 9., 2., 6.])
            .text_array(vec![
                "Filled Triangle",
                "Filled Polygon",
                "Quadratic Bezier Curves",
                "Cubic Bezier Curves",
            ])
            .mode(Mode::Text),
    );

    let mut layout = Layout::new()
        .x_axis(
            Axis::new()
                .domain(&[0.05, 0.95])
                .range(vec![0., 9.])
                .zero_line(false),
        )
        .y_axis(
            Axis::new()
                .domain(&[0.05, 0.95])
                .range(vec![0, 11])
                .zero_line(false),
        );
    layout.add_shape(
        Shape::new()
            .shape_type(ShapeType::Path)
            .path("M 4,4 Q 6,0 8,4")
            .line(ShapeLine::new().color(NamedColor::RoyalBlue)),
    );
    layout.add_shape(
        Shape::new()
            .shape_type(ShapeType::Path)
            .path("M 1,4 C 2,8 6,4 8,8")
            .line(ShapeLine::new().color(NamedColor::MediumPurple)),
    );
    layout.add_shape(
        Shape::new()
            .shape_type(ShapeType::Path)
            .path("M 1 1 L 1 3 L 4 1 Z")
            .fill_color(NamedColor::LightPink)
            .line(ShapeLine::new().color(NamedColor::Crimson)),
    );
    layout.add_shape(
        Shape::new()
            .shape_type(ShapeType::Path)
            .path("M 3,7 L2,8 L2,9 L3,10, L4,10 L5,9 L5,8 L4,7 Z")
            .fill_color(NamedColor::PaleTurquoise)
            .line(ShapeLine::new().color(NamedColor::LightSeaGreen)),
    );

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Recipes

Most of the recipes presented here have been adapted from the official documentation for plotly.js and plotly.py. Contributions of interesting plots that showcase the capabilities of the library are most welcome. For more information on the process please see the contributing guidelines.

Basic Charts

The source code for the following examples can also be found here.

KindLink
Scatter PlotsScatter Plots
Line ChartsLine Charts
Bar ChartsScatter Plots
Sankey DiagramsSankey Diagrams

Scatter Plots

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use ndarray::Array;
use plotly::common::{
    ColorScale, ColorScalePalette, DashType, Fill, Font, Line, LineShape, Marker, Mode, Title,
};
use plotly::layout::{Axis, BarMode, Layout, Legend, TicksDirection};
use plotly::{Bar, color::{NamedColor, Rgb, Rgba}, Plot, Scatter};
use rand_distr::{Distribution, Normal, Uniform};
}

The to_inline_html method is used to produce the html plot displayed in this page.

Simple Scatter Plot

#![allow(unused)]
fn main() {
fn simple_scatter_plot(show: bool) -> Plot {
    let n: usize = 100;
    let t: Vec<f64> = Array::linspace(0., 10., n).into_raw_vec_and_offset().0;
    let y: Vec<f64> = t.iter().map(|x| x.sin()).collect();

    let trace = Scatter::new(t, y).mode(Mode::Markers);
    let mut plot = Plot::new();
    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Line and Scatter Plots

#![allow(unused)]
fn main() {
fn line_and_scatter_plots(show: bool) -> Plot {
    let n: usize = 100;
    let mut rng = rand::thread_rng();
    let random_x: Vec<f64> = Array::linspace(0., 1., n).into_raw_vec_and_offset().0;
    let random_y0: Vec<f64> = Normal::new(5., 1.)
        .unwrap()
        .sample_iter(&mut rng)
        .take(n)
        .collect();
    let random_y1: Vec<f64> = Normal::new(0., 1.)
        .unwrap()
        .sample_iter(&mut rng)
        .take(n)
        .collect();
    let random_y2: Vec<f64> = Normal::new(-5., 1.)
        .unwrap()
        .sample_iter(&mut rng)
        .take(n)
        .collect();

    let trace1 = Scatter::new(random_x.clone(), random_y0)
        .mode(Mode::Markers)
        .name("markers");
    let trace2 = Scatter::new(random_x.clone(), random_y1)
        .mode(Mode::LinesMarkers)
        .name("linex+markers");
    let trace3 = Scatter::new(random_x, random_y2)
        .mode(Mode::Lines)
        .name("lines");

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);

    if show {
        plot.show();
    }
    plot
}
}

Bubble Scatter Plots

#![allow(unused)]
fn main() {
fn bubble_scatter_plots(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![10, 11, 12, 13])
        .mode(Mode::Markers)
        .marker(
            Marker::new()
                .size_array(vec![40, 60, 80, 100])
                .color_array(vec![
                    NamedColor::Red,
                    NamedColor::Blue,
                    NamedColor::Cyan,
                    NamedColor::OrangeRed,
                ]),
        );
    let mut plot = Plot::new();
    plot.add_trace(trace1);

    if show {
        plot.show();
    }
    plot
}
}

Data Labels Hover

#![allow(unused)]
fn main() {
fn data_labels_hover(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3, 4, 5], vec![1, 6, 3, 6, 1])
        .mode(Mode::Markers)
        .name("Team A")
        .marker(Marker::new().size(12));
    let trace2 = Scatter::new(vec![1.5, 2.5, 3.5, 4.5, 5.5], vec![4, 1, 7, 1, 4])
        .mode(Mode::Markers)
        .name("Team B")
        .marker(Marker::new().size(12));

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    let layout = Layout::new()
        .title("Data Labels Hover")
        .x_axis(Axis::new().title("x").range(vec![0.75, 5.25]))
        .y_axis(Axis::new().title("y").range(vec![0., 8.]));
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Data Labels on the Plot

#![allow(unused)]
fn main() {
fn data_labels_on_the_plot(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3, 4, 5], vec![1, 6, 3, 6, 1])
        .mode(Mode::Markers)
        .name("Team A")
        .marker(Marker::new().size(12))
        .text_array(vec!["A-1", "A-2", "A-3", "A-4", "A-5"]);
    let trace2 = Scatter::new(vec![1.5, 2.5, 3.5, 4.5, 5.5], vec![4, 1, 7, 1, 4])
        .mode(Mode::Markers)
        .name("Team B")
        .text_array(vec!["B-a", "B-b", "B-c", "B-d", "B-e"])
        .marker(Marker::new().size(12));

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    let layout = Layout::new()
        .title("Data Labels on the Plot")
        .x_axis(Axis::new().range(vec![0.75, 5.25]))
        .y_axis(Axis::new().range(vec![0., 8.]));
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Colored and Styled Scatter Plot

#![allow(unused)]
fn main() {
fn colored_and_styled_scatter_plot(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![52698, 43117], vec![53, 31])
        .mode(Mode::Markers)
        .name("North America")
        .text_array(vec!["United States", "Canada"])
        .marker(
            Marker::new()
                .color(Rgb::new(164, 194, 244))
                .size(12)
                .line(Line::new().color(NamedColor::White).width(0.5)),
        );
    let trace2 = Scatter::new(
        vec![
            39317, 37236, 35650, 30066, 29570, 27159, 23557, 21046, 18007,
        ],
        vec![33, 20, 13, 19, 27, 19, 49, 44, 38],
    )
    .mode(Mode::Markers)
    .name("Europe")
    .text_array(vec![
        "Germany",
        "Britain",
        "France",
        "Spain",
        "Italy",
        "Czech Rep.",
        "Greece",
        "Poland",
    ])
    .marker(Marker::new().color(Rgb::new(255, 217, 102)).size(12));
    let trace3 = Scatter::new(
        vec![42952, 37037, 33106, 17478, 9813, 5253, 4692, 3899],
        vec![23, 42, 54, 89, 14, 99, 93, 70],
    )
    .mode(Mode::Markers)
    .name("Asia/Pacific")
    .text_array(vec![
        "Australia",
        "Japan",
        "South Korea",
        "Malaysia",
        "China",
        "Indonesia",
        "Philippines",
        "India",
    ])
    .marker(Marker::new().color(Rgb::new(234, 153, 153)).size(12));
    let trace4 = Scatter::new(
        vec![19097, 18601, 15595, 13546, 12026, 7434, 5419],
        vec![43, 47, 56, 80, 86, 93, 80],
    )
    .mode(Mode::Markers)
    .name("Latin America")
    .text_array(vec![
        "Chile",
        "Argentina",
        "Mexico",
        "Venezuela",
        "Venezuela",
        "El Salvador",
        "Bolivia",
    ])
    .marker(Marker::new().color(Rgb::new(142, 124, 195)).size(12));

    let layout = Layout::new()
        .title("Quarter 1 Growth")
        .x_axis(
            Axis::new()
                .title("GDP per Capita")
                .show_grid(false)
                .zero_line(false),
        )
        .y_axis(Axis::new().title("Percent").show_line(false));
    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);
    plot.add_trace(trace4);
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Large Data Sets

#![allow(unused)]
fn main() {
fn large_data_sets(show: bool) -> Plot {
    let n: usize = 100_000;
    let mut rng = rand::thread_rng();
    let r: Vec<f64> = Uniform::new(0., 1.).sample_iter(&mut rng).take(n).collect();
    let theta: Vec<f64> = Normal::new(0., 2. * std::f64::consts::PI)
        .unwrap()
        .sample_iter(&mut rng)
        .take(n)
        .collect();

    let x: Vec<f64> = r
        .iter()
        .zip(theta.iter())
        .map(|args| args.0 * args.1.cos())
        .collect();
    let y: Vec<f64> = r
        .iter()
        .zip(theta.iter())
        .map(|args| args.0 * args.1.sin())
        .collect();
    let trace = Scatter::new(x, y)
        .web_gl_mode(true)
        .mode(Mode::Markers)
        .marker(
            Marker::new()
                .color_scale(ColorScale::Palette(ColorScalePalette::Viridis))
                .line(Line::new().width(1.)),
        );
    let mut plot = Plot::new();
    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Line Charts

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use ndarray::Array;
use plotly::common::{
    ColorScale, ColorScalePalette, DashType, Fill, Font, Line, LineShape, Marker, Mode, Title,
};
use plotly::layout::{Axis, BarMode, Layout, Legend, TicksDirection};
use plotly::{Bar, color::{NamedColor, Rgb, Rgba}, Plot, Scatter};
use rand_distr::{Distribution, Normal, Uniform};
}

The to_inline_html method is used to produce the html plot displayed in this page.

Adding Names to Line and Scatter Plot

#![allow(unused)]
fn main() {
fn adding_names_to_line_and_scatter_plot(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![10, 15, 13, 17])
        .mode(Mode::Markers)
        .name("Scatter");
    let trace2 = Scatter::new(vec![2, 3, 4, 5], vec![16, 5, 11, 9])
        .mode(Mode::Lines)
        .name("Lines");
    let trace3 = Scatter::new(vec![1, 2, 3, 4], vec![12, 9, 15, 12])
        .mode(Mode::LinesMarkers)
        .name("Scatter + Lines");

    let layout = Layout::new().title("Adding Names to Line and Scatter Plot");
    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Line and Scatter Styling

#![allow(unused)]
fn main() {
fn line_and_scatter_styling(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![10, 15, 13, 17])
        .mode(Mode::Markers)
        .name("trace1")
        .marker(Marker::new().color(Rgb::new(219, 64, 82)).size(12));
    let trace2 = Scatter::new(vec![2, 3, 4, 5], vec![16, 5, 11, 9])
        .mode(Mode::Lines)
        .name("trace2")
        .line(Line::new().color(Rgb::new(55, 128, 191)).width(3.0));
    let trace3 = Scatter::new(vec![1, 2, 3, 4], vec![12, 9, 15, 12])
        .mode(Mode::LinesMarkers)
        .name("trace3")
        .marker(Marker::new().color(Rgb::new(128, 0, 128)).size(12))
        .line(Line::new().color(Rgb::new(128, 0, 128)).width(1.0));

    let layout = Layout::new().title("Line and Scatter Styling");
    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Styling Line Plot

#![allow(unused)]
fn main() {
fn styling_line_plot(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![10, 15, 13, 17])
        .mode(Mode::Markers)
        .name("Red")
        .line(Line::new().color(Rgb::new(219, 64, 82)).width(3.0));
    let trace2 = Scatter::new(vec![1, 2, 3, 4], vec![12, 9, 15, 12])
        .mode(Mode::LinesMarkers)
        .name("Blue")
        .line(Line::new().color(Rgb::new(55, 128, 191)).width(1.0));

    let layout = Layout::new()
        .title("Styling Line Plot")
        .width(500)
        .height(500);
    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Line Shape Options for Interpolation

#![allow(unused)]
fn main() {
fn line_shape_options_for_interpolation(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3, 4, 5], vec![1, 3, 2, 3, 1])
        .mode(Mode::LinesMarkers)
        .name("linear")
        .line(Line::new().shape(LineShape::Linear));
    let trace2 = Scatter::new(vec![1, 2, 3, 4, 5], vec![6, 8, 7, 8, 6])
        .mode(Mode::LinesMarkers)
        .name("spline")
        .line(Line::new().shape(LineShape::Spline));
    let trace3 = Scatter::new(vec![1, 2, 3, 4, 5], vec![11, 13, 12, 13, 11])
        .mode(Mode::LinesMarkers)
        .name("vhv")
        .line(Line::new().shape(LineShape::Vhv));
    let trace4 = Scatter::new(vec![1, 2, 3, 4, 5], vec![16, 18, 17, 18, 16])
        .mode(Mode::LinesMarkers)
        .name("hvh")
        .line(Line::new().shape(LineShape::Hvh));
    let trace5 = Scatter::new(vec![1, 2, 3, 4, 5], vec![21, 23, 22, 23, 21])
        .mode(Mode::LinesMarkers)
        .name("vh")
        .line(Line::new().shape(LineShape::Vh));
    let trace6 = Scatter::new(vec![1, 2, 3, 4, 5], vec![26, 28, 27, 28, 26])
        .mode(Mode::LinesMarkers)
        .name("hv")
        .line(Line::new().shape(LineShape::Hv));

    let mut plot = Plot::new();
    let layout = Layout::new().legend(
        Legend::new()
            .y(0.5)
            .trace_order(TraceOrder::Reversed)
            .font(Font::new().size(16)),
    );
    plot.set_layout(layout);
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);
    plot.add_trace(trace4);
    plot.add_trace(trace5);
    plot.add_trace(trace6);

    if show {
        plot.show();
    }
    plot
}
}

Line Dash

#![allow(unused)]
fn main() {
fn line_dash(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3, 4, 5], vec![1, 3, 2, 3, 1])
        .mode(Mode::LinesMarkers)
        .name("solid")
        .line(Line::new().dash(DashType::Solid));
    let trace2 = Scatter::new(vec![1, 2, 3, 4, 5], vec![6, 8, 7, 8, 6])
        .mode(Mode::LinesMarkers)
        .name("dashdot")
        .line(Line::new().dash(DashType::DashDot));
    let trace3 = Scatter::new(vec![1, 2, 3, 4, 5], vec![11, 13, 12, 13, 11])
        .mode(Mode::LinesMarkers)
        .name("dash")
        .line(Line::new().dash(DashType::Dash));
    let trace4 = Scatter::new(vec![1, 2, 3, 4, 5], vec![16, 18, 17, 18, 16])
        .mode(Mode::LinesMarkers)
        .name("dot")
        .line(Line::new().dash(DashType::Dot));
    let trace5 = Scatter::new(vec![1, 2, 3, 4, 5], vec![21, 23, 22, 23, 21])
        .mode(Mode::LinesMarkers)
        .name("longdash")
        .line(Line::new().dash(DashType::LongDash));
    let trace6 = Scatter::new(vec![1, 2, 3, 4, 5], vec![26, 28, 27, 28, 26])
        .mode(Mode::LinesMarkers)
        .name("longdashdot")
        .line(Line::new().dash(DashType::LongDashDot));

    let mut plot = Plot::new();
    let layout = Layout::new()
        .legend(
            Legend::new()
                .y(0.5)
                .trace_order(TraceOrder::Reversed)
                .font(Font::new().size(16)),
        )
        .x_axis(Axis::new().range(vec![0.95, 5.05]).auto_range(false))
        .y_axis(Axis::new().range(vec![0.0, 28.5]).auto_range(false));
    plot.set_layout(layout);
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);
    plot.add_trace(trace4);
    plot.add_trace(trace5);
    plot.add_trace(trace6);

    if show {
        plot.show();
    }
    plot
}
}

Filled Lines

#![allow(unused)]
fn main() {
fn filled_lines(show: bool) -> Plot {
    let x1 = vec![
        1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 10.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0,
        2.0, 1.0,
    ];
    let x2 = (1..=10).map(|iv| iv as f64).collect::<Vec<f64>>();
    let trace1 = Scatter::new(
        x1.clone(),
        vec![
            2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0,
            2.0, 1.0, 0.0,
        ],
    )
    .fill(Fill::ToZeroX)
    .fill_color(Rgba::new(0, 100, 80, 0.2))
    .line(Line::new().color(NamedColor::Transparent))
    .name("Fair")
    .show_legend(false);
    let trace2 = Scatter::new(
        x1.clone(),
        vec![
            5.5, 3.0, 5.5, 8.0, 6.0, 3.0, 8.0, 5.0, 6.0, 5.5, 4.75, 5.0, 4.0, 7.0, 2.0, 4.0, 7.0,
            4.4, 2.0, 4.5,
        ],
    )
    .fill(Fill::ToZeroX)
    .fill_color(Rgba::new(0, 176, 246, 0.2))
    .line(Line::new().color(NamedColor::Transparent))
    .name("Premium")
    .show_legend(false);
    let trace3 = Scatter::new(
        x1,
        vec![
            11.0, 9.0, 7.0, 5.0, 3.0, 1.0, 3.0, 5.0, 3.0, 1.0, -1.0, 1.0, 3.0, 1.0, -0.5, 1.0, 3.0,
            5.0, 7.0, 9.0,
        ],
    )
    .fill(Fill::ToZeroX)
    .fill_color(Rgba::new(231, 107, 243, 0.2))
    .line(Line::new().color(NamedColor::Transparent))
    .name("Fair")
    .show_legend(false);
    let trace4 = Scatter::new(
        x2.clone(),
        vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
    )
    .line(Line::new().color(Rgb::new(0, 100, 80)))
    .name("Fair");
    let trace5 = Scatter::new(
        x2.clone(),
        vec![5.0, 2.5, 5.0, 7.5, 5.0, 2.5, 7.5, 4.5, 5.5, 5.0],
    )
    .line(Line::new().color(Rgb::new(0, 176, 246)))
    .name("Premium");
    let trace6 = Scatter::new(x2, vec![10.0, 8.0, 6.0, 4.0, 2.0, 0.0, 2.0, 4.0, 2.0, 0.0])
        .line(Line::new().color(Rgb::new(231, 107, 243)))
        .name("Ideal");

    let layout = Layout::new()
        .paper_background_color(Rgb::new(255, 255, 255))
        .plot_background_color(Rgb::new(229, 229, 229))
        .x_axis(
            Axis::new()
                .grid_color(Rgb::new(255, 255, 255))
                .range(vec![1.0, 10.0])
                .show_grid(true)
                .show_line(false)
                .show_tick_labels(true)
                .tick_color(Rgb::new(127, 127, 127))
                .ticks(TicksDirection::Outside)
                .zero_line(false),
        )
        .y_axis(
            Axis::new()
                .grid_color(Rgb::new(255, 255, 255))
                .show_grid(true)
                .show_line(false)
                .show_tick_labels(true)
                .tick_color(Rgb::new(127, 127, 127))
                .ticks(TicksDirection::Outside)
                .zero_line(false),
        );

    let mut plot = Plot::new();
    plot.set_layout(layout);
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);
    plot.add_trace(trace4);
    plot.add_trace(trace5);
    plot.add_trace(trace6);

    if show {
        plot.show();
    }
    plot
}
}

Bar Charts

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use ndarray::Array;
use plotly::common::{
    ColorScale, ColorScalePalette, DashType, Fill, Font, Line, LineShape, Marker, Mode, Title,
};
use plotly::layout::{Axis, BarMode, Layout, Legend, TicksDirection};
use plotly::{Bar, color::{NamedColor, Rgb, Rgba}, Plot, Scatter};
use rand_distr::{Distribution, Normal, Uniform};
}

The to_inline_html method is used to produce the html plot displayed in this page.

Basic Bar Chart

#![allow(unused)]
fn main() {
fn basic_bar_chart(show: bool) -> Plot {
    let animals = vec!["giraffes", "orangutans", "monkeys"];
    let t = Bar::new(animals, vec![20, 14, 23]);
    let mut plot = Plot::new();
    plot.add_trace(t);

    if show {
        plot.show();
    }
    plot
}
}

Grouped Bar Chart

#![allow(unused)]
fn main() {
fn grouped_bar_chart(show: bool) -> Plot {
    let animals1 = vec!["giraffes", "orangutans", "monkeys"];
    let trace1 = Bar::new(animals1, vec![20, 14, 23]).name("SF Zoo");

    let animals2 = vec!["giraffes", "orangutans", "monkeys"];
    let trace2 = Bar::new(animals2, vec![12, 18, 29]).name("LA Zoo");

    let layout = Layout::new().bar_mode(BarMode::Group);

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Stacked Bar Chart

#![allow(unused)]
fn main() {
fn stacked_bar_chart(show: bool) -> Plot {
    let animals1 = vec!["giraffes", "orangutans", "monkeys"];
    let trace1 = Bar::new(animals1, vec![20, 14, 23]).name("SF Zoo");

    let animals2 = vec!["giraffes", "orangutans", "monkeys"];
    let trace2 = Bar::new(animals2, vec![12, 18, 29]).name("LA Zoo");

    let layout = Layout::new().bar_mode(BarMode::Stack);

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Sankey Diagrams

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use ndarray::Array;
use plotly::common::{
    ColorScale, ColorScalePalette, DashType, Fill, Font, Line, LineShape, Marker, Mode, Title,
};
use plotly::layout::{Axis, BarMode, Layout, Legend, TicksDirection};
use plotly::Sankey;
use rand_distr::{Distribution, Normal, Uniform};
}

The to_inline_html method is used to produce the html plot displayed in this page.

Constructing a basic Sankey diagram

#![allow(unused)]
fn main() {
let trace = Sankey::new()
        .orientation(Orientation::Horizontal)
        .node(
            Node::new()
                .pad(15)
                .thickness(30)
                .line(SankeyLine::new().color(NamedColor::Black).width(0.5))
                .label(vec!["A1", "A2", "B1", "B2", "C1", "C2"])
                .color_array(vec![
                    NamedColor::Blue,
                    NamedColor::Blue,
                    NamedColor::Blue,
                    NamedColor::Blue,
                    NamedColor::Blue,
                    NamedColor::Blue,
                ]),
        )
        .link(
            Link::new()
                .value(vec![8, 4, 2, 8, 4, 2])
                .source(vec![0, 1, 0, 2, 3, 3])
                .target(vec![2, 3, 3, 4, 4, 5]),
        );

    let layout = Layout::new()
        .title("Basic Sankey".into())
        .font(Font::new().size(10));

    let mut plot = Plot::new();
    plot.add_trace(trace);
    plot.set_layout(layout);

    if show {
        plot.show();
    }
}
}

Statistical Charts

The complete source code for the following examples can also be found here.

KindLink
Error BarsScatter Plots
Box PlotsLine Charts
HistogramsScatter Plots

Error Bars

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use ndarray::Array;
use plotly::box_plot::{BoxMean, BoxPoints};
use plotly::common::{ErrorData, ErrorType, Line, Marker, Mode, Orientation, Title};
use plotly::histogram::{Bins, Cumulative, HistFunc, HistNorm};
use plotly::layout::{Axis, BarMode, BoxMode, Layout, Margin};
use plotly::{Bar, BoxPlot, Histogram, Plot, color::{NamedColor, Rgb, Rgba}, Scatter};
use rand_distr::{Distribution, Normal, Uniform};

}

The to_inline_html method is used to produce the html plot displayed in this page.

Basic Symmetric Error Bars

#![allow(unused)]
fn main() {
fn basic_symmetric_error_bars(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![0, 1, 2], vec![6, 10, 2])
        .name("trace1")
        .error_y(ErrorData::new(ErrorType::Data).array(vec![1.0, 2.0, 3.0]));

    let mut plot = Plot::new();
    plot.add_trace(trace1);

    if show {
        plot.show();
    }
    plot
}
}

Asymmetric Error Bars

#![allow(unused)]
fn main() {
fn asymmetric_error_bars(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![2, 1, 3, 4])
        .name("trace1")
        .error_y(
            ErrorData::new(ErrorType::Data)
                .array(vec![0.1, 0.2, 0.1, 0.1])
                .array_minus(vec![0.2, 0.4, 1., 0.2]),
        );

    let mut plot = Plot::new();
    plot.add_trace(trace1);

    if show {
        plot.show();
    }
    plot
}
}

Error Bars as a Percentage of the Y Value

#![allow(unused)]
fn main() {
fn error_bars_as_a_percentage_of_the_y_value(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![0, 1, 2], vec![6, 10, 2])
        .name("trace1")
        .error_y(ErrorData::new(ErrorType::Percent).value(50.).visible(true));

    let mut plot = Plot::new();
    plot.add_trace(trace1);

    if show {
        plot.show();
    }
    plot
}
}

Asymmetric Error Bars with a Constant Offset

#![allow(unused)]
fn main() {
fn asymmetric_error_bars_with_a_constant_offset(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![2, 1, 3, 4])
        .name("trace1")
        .error_y(
            ErrorData::new(ErrorType::Percent)
                .symmetric(false)
                .value(15.)
                .value_minus(25.),
        );

    let mut plot = Plot::new();
    plot.add_trace(trace1);

    if show {
        plot.show();
    }
    plot
}
}

Horizontal Error Bars

#![allow(unused)]
fn main() {
fn horizontal_error_bars(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3, 4], vec![2, 1, 3, 4])
        .name("trace1")
        .error_x(ErrorData::new(ErrorType::Percent).value(10.));

    let mut plot = Plot::new();
    plot.add_trace(trace1);

    if show {
        plot.show();
    }
    plot
}
}

Bar Chart with Error Bars

#![allow(unused)]
fn main() {
fn bar_chart_with_error_bars(show: bool) -> Plot {
    let trace_c = Bar::new(vec!["Trial 1", "Trial 2", "Trial 3"], vec![3, 6, 4])
        .error_y(ErrorData::new(ErrorType::Data).array(vec![1., 0.5, 1.5]));
    let trace_e = Bar::new(vec!["Trial 1", "Trial 2", "Trial 3"], vec![4, 7, 3])
        .error_y(ErrorData::new(ErrorType::Data).array(vec![0.5, 1., 2.]));

    let mut plot = Plot::new();
    plot.add_trace(trace_c);
    plot.add_trace(trace_e);

    let layout = Layout::new().bar_mode(BarMode::Group);
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Colored and Styled Error Bars

#![allow(unused)]
fn main() {
fn colored_and_styled_error_bars(show: bool) -> Plot {
    let x_theo: Vec<f64> = Array::linspace(-4., 4., 100).into_raw_vec_and_offset().0;
    let sincx: Vec<f64> = x_theo
        .iter()
        .map(|x| (x * std::f64::consts::PI).sin() / (*x * std::f64::consts::PI))
        .collect();
    let x = vec![
        -3.8, -3.03, -1.91, -1.46, -0.89, -0.24, -0.0, 0.41, 0.89, 1.01, 1.91, 2.28, 2.79, 3.56,
    ];
    let y = vec![
        -0.02, 0.04, -0.01, -0.27, 0.36, 0.75, 1.03, 0.65, 0.28, 0.02, -0.11, 0.16, 0.04, -0.15,
    ];

    let trace1 = Scatter::new(x_theo, sincx).name("sinc(x)");
    let trace2 = Scatter::new(x, y)
        .mode(Mode::Markers)
        .name("measured")
        .error_y(
            ErrorData::new(ErrorType::Constant)
                .value(0.1)
                .color(NamedColor::Purple)
                .thickness(1.5)
                .width(3),
        )
        .error_x(
            ErrorData::new(ErrorType::Constant)
                .value(0.2)
                .color(NamedColor::Purple)
                .thickness(1.5)
                .width(3),
        )
        .marker(Marker::new().color(NamedColor::Purple).size(8));

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    if show {
        plot.show();
    }
    plot
}
}

Box Plots

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use ndarray::Array;
use plotly::box_plot::{BoxMean, BoxPoints};
use plotly::common::{ErrorData, ErrorType, Line, Marker, Mode, Orientation, Title};
use plotly::histogram::{Bins, Cumulative, HistFunc, HistNorm};
use plotly::layout::{Axis, BarMode, BoxMode, Layout, Margin};
use plotly::{Bar, BoxPlot, Histogram, color::{NamedColor, Rgb, Rgba}, Scatter};
use rand_distr::{Distribution, Normal, Uniform};

}

The to_inline_html method is used to produce the html plot displayed in this page.

Basic Box Plot

#![allow(unused)]
fn main() {
fn basic_box_plot(show: bool) -> Plot {
    let mut rng = rand::thread_rng();
    let uniform1 = Uniform::new(0.0, 1.0);
    let uniform2 = Uniform::new(1.0, 2.0);
    let n = 50;

    let mut y0 = Vec::with_capacity(n);
    let mut y1 = Vec::with_capacity(n);

    for _ in 0..n {
        y0.push(uniform1.sample(&mut rng));
        y1.push(uniform2.sample(&mut rng));
    }

    let trace1 = BoxPlot::<f64, f64>::new(y0);
    let trace2 = BoxPlot::<f64, f64>::new(y1);
    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    if show {
        plot.show();
    }
    plot
}
}

Box Plot that Displays the Underlying Data

#![allow(unused)]
fn main() {
fn box_plot_that_displays_the_underlying_data(show: bool) -> Plot {
    let trace1 = BoxPlot::new(vec![0, 1, 1, 2, 3, 5, 8, 13, 21])
        .box_points(BoxPoints::All)
        .jitter(0.3)
        .point_pos(-1.8);
    let mut plot = Plot::new();
    plot.add_trace(trace1);

    if show {
        plot.show();
    }
    plot
}
}

Horizontal Box Plot

#![allow(unused)]
fn main() {
fn horizontal_box_plot(show: bool) -> Plot {
    let x = vec![
        "Set 1", "Set 1", "Set 1", "Set 1", "Set 1", "Set 1", "Set 1", "Set 1", "Set 1", "Set 2",
        "Set 2", "Set 2", "Set 2", "Set 2", "Set 2", "Set 2", "Set 2", "Set 2",
    ];

    let trace = BoxPlot::new_xy(
        vec![1, 2, 3, 4, 4, 4, 8, 9, 10, 2, 3, 3, 3, 3, 5, 6, 6, 7],
        x.clone(),
    )
    .orientation(Orientation::Horizontal);

    let mut plot = Plot::new();
    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Grouped Box Plot

#![allow(unused)]
fn main() {
fn grouped_box_plot(show: bool) -> Plot {
    let x = vec![
        "day 1", "day 1", "day 1", "day 1", "day 1", "day 1", "day 2", "day 2", "day 2", "day 2",
        "day 2", "day 2",
    ];

    let trace1 = BoxPlot::new_xy(
        x.clone(),
        vec![0.2, 0.2, 0.6, 1.0, 0.5, 0.4, 0.2, 0.7, 0.9, 0.1, 0.5, 0.3],
    );
    let trace2 = BoxPlot::new_xy(
        x.clone(),
        vec![0.6, 0.7, 0.3, 0.6, 0.0, 0.5, 0.7, 0.9, 0.5, 0.8, 0.7, 0.2],
    );
    let trace3 = BoxPlot::new_xy(
        x.clone(),
        vec![0.1, 0.3, 0.1, 0.9, 0.6, 0.6, 0.9, 1.0, 0.3, 0.6, 0.8, 0.5],
    );

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);

    let layout = Layout::new()
        .y_axis(Axis::new().title("normalized moisture").zero_line(false))
        .box_mode(BoxMode::Group);

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Box Plot Styling Outliers

#![allow(unused)]
fn main() {
fn box_plot_styling_outliers(show: bool) -> Plot {
    let y = vec![
        0.75, 5.25, 5.5, 6.0, 6.2, 6.6, 6.80, 7.0, 7.2, 7.5, 7.5, 7.75, 8.15, 8.15, 8.65, 8.93,
        9.2, 9.5, 10.0, 10.25, 11.5, 12.0, 16.0, 20.90, 22.3, 23.25,
    ];
    let trace1 = BoxPlot::new(y.clone())
        .name("All Points")
        .jitter(0.3)
        .point_pos(-1.8)
        .marker(Marker::new().color(Rgb::new(7, 40, 89)))
        .box_points(BoxPoints::All);
    let trace2 = BoxPlot::new(y.clone())
        .name("Only Whiskers")
        .marker(Marker::new().color(Rgb::new(9, 56, 125)))
        .box_points(BoxPoints::False);
    let trace3 = BoxPlot::new(y.clone())
        .name("Suspected Outlier")
        .marker(
            Marker::new()
                .color(Rgb::new(8, 81, 156))
                .outlier_color(Rgba::new(219, 64, 82, 0.6))
                .line(
                    Line::new()
                        .outlier_color(Rgba::new(219, 64, 82, 1.0))
                        .outlier_width(2),
                ),
        )
        .box_points(BoxPoints::SuspectedOutliers);
    let trace4 = BoxPlot::new(y)
        .name("Whiskers and Outliers")
        .marker(Marker::new().color(Rgb::new(107, 174, 214)))
        .box_points(BoxPoints::Outliers);

    let layout = Layout::new().title("Box Plot Styling Outliers");

    let mut plot = Plot::new();
    plot.set_layout(layout);
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);
    plot.add_trace(trace4);

    if show {
        plot.show();
    }
    plot
}
}

Box Plot Styling Mean and Standard Deviation

#![allow(unused)]
fn main() {
fn box_plot_styling_mean_and_standard_deviation(show: bool) -> Plot {
    let y = vec![
        2.37, 2.16, 4.82, 1.73, 1.04, 0.23, 1.32, 2.91, 0.11, 4.51, 0.51, 3.75, 1.35, 2.98, 4.50,
        0.18, 4.66, 1.30, 2.06, 1.19,
    ];

    let trace1 = BoxPlot::new(y.clone())
        .name("Only Mean")
        .marker(Marker::new().color(Rgb::new(8, 81, 156)))
        .box_mean(BoxMean::True);
    let trace2 = BoxPlot::new(y)
        .name("Mean and Standard Deviation")
        .marker(Marker::new().color(Rgb::new(8, 81, 156)))
        .box_mean(BoxMean::StandardDeviation);
    let layout = Layout::new().title("Box Plot Styling Mean and Standard Deviation");

    let mut plot = Plot::new();
    plot.set_layout(layout);
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    if show {
        plot.show();
    }
    plot
}
}

Grouped Horizontal Box Plot

#![allow(unused)]
fn main() {
fn grouped_horizontal_box_plot(show: bool) -> Plot {
    let x = vec![
        "day 1", "day 1", "day 1", "day 1", "day 1", "day 1", "day 2", "day 2", "day 2", "day 2",
        "day 2", "day 2",
    ];

    let trace1 = BoxPlot::new_xy(
        vec![0.2, 0.2, 0.6, 1.0, 0.5, 0.4, 0.2, 0.7, 0.9, 0.1, 0.5, 0.3],
        x.clone(),
    )
    .name("Kale")
    .marker(Marker::new().color("3D9970"))
    .box_mean(BoxMean::False)
    .orientation(Orientation::Horizontal);
    let trace2 = BoxPlot::new_xy(
        vec![0.6, 0.7, 0.3, 0.6, 0.0, 0.5, 0.7, 0.9, 0.5, 0.8, 0.7, 0.2],
        x.clone(),
    )
    .name("Radishes")
    .marker(Marker::new().color("FF4136"))
    .box_mean(BoxMean::False)
    .orientation(Orientation::Horizontal);
    let trace3 = BoxPlot::new_xy(
        vec![0.1, 0.3, 0.1, 0.9, 0.6, 0.6, 0.9, 1.0, 0.3, 0.6, 0.8, 0.5],
        x.clone(),
    )
    .name("Carrots")
    .marker(Marker::new().color("FF851B"))
    .box_mean(BoxMean::False)
    .orientation(Orientation::Horizontal);

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);

    let layout = Layout::new()
        .title("Grouped Horizontal Box Plot")
        .x_axis(Axis::new().title("normalized moisture").zero_line(false))
        .box_mode(BoxMode::Group);

    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Fully Styled Box Plot

#![allow(unused)]
fn main() {
fn fully_styled_box_plot(show: bool) -> Plot {
    let rnd_sample = |num, mul| -> Vec<f64> {
        let mut v: Vec<f64> = Vec::with_capacity(num);
        let mut rng = rand::thread_rng();
        let uniform = Uniform::new(0.0, mul);
        for _ in 0..num {
            v.push(uniform.sample(&mut rng));
        }
        v
    };

    let x_data = [
        "Carmelo<br>Anthony",
        "Dwyane<br>Wade",
        "Deron<br>Williams",
        "Brook<br>Lopez",
        "Damian<br>Lillard",
        "David<br>West",
        "Blake<br>Griffin",
        "David<br>Lee",
        "Demar<br>Derozan",
    ];
    let y_data = vec![
        rnd_sample(30, 10.0),
        rnd_sample(30, 20.0),
        rnd_sample(30, 25.0),
        rnd_sample(30, 40.0),
        rnd_sample(30, 45.0),
        rnd_sample(30, 30.0),
        rnd_sample(30, 20.0),
        rnd_sample(30, 15.0),
        rnd_sample(30, 43.0),
    ];

    let mut plot = Plot::new();
    let layout = Layout::new()
        .title("Points Scored by the Top 9 Scoring NBA Players in 2012")
        .y_axis(
            Axis::new()
                .auto_range(true)
                .show_grid(true)
                .zero_line(true)
                .dtick(5.0)
                .grid_color(Rgb::new(255, 255, 255))
                .grid_width(1)
                .zero_line_color(Rgb::new(255, 255, 255))
                .zero_line_width(2),
        )
        .margin(Margin::new().left(40).right(30).bottom(80).top(100))
        .paper_background_color(Rgb::new(243, 243, 243))
        .plot_background_color(Rgb::new(243, 243, 243))
        .show_legend(false);
    plot.set_layout(layout);

    for index in 0..x_data.len() {
        let trace = BoxPlot::new(y_data[index].clone())
            .name(x_data[index])
            .box_points(BoxPoints::All)
            .jitter(0.5)
            .whisker_width(0.2)
            .marker(Marker::new().size(6))
            .line(Line::new().width(2.0));
        plot.add_trace(trace);
    }

    if show {
        plot.show();
    }
    plot
}
}

Histograms

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use ndarray::Array;
use plotly::box_plot::{BoxMean, BoxPoints};
use plotly::common::{ErrorData, ErrorType, Line, Marker, Mode, Orientation, Title};
use plotly::histogram::{Bins, Cumulative, HistFunc, HistNorm};
use plotly::layout::{Axis, BarMode, BoxMode, Layout, Margin};
use plotly::{Bar, BoxPlot, Histogram, Plot, color::{NamedColor, Rgb, Rgba}, Scatter};
use rand_distr::{Distribution, Normal, Uniform};

}

The to_inline_html method is used to produce the html plot displayed in this page.

Basic Histogram

#![allow(unused)]
fn main() {
fn basic_histogram(show: bool) -> Plot {
    let samples = sample_normal_distribution(10_000, 0.0, 1.0);
    let trace = Histogram::new(samples).name("h");
    let mut plot = Plot::new();
    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Horizontal Histogram

#![allow(unused)]
fn main() {
fn horizontal_histogram(show: bool) -> Plot {
    let samples = sample_normal_distribution(10_000, 0.0, 1.0);
    let trace = Histogram::new_vertical(samples)
        .name("h")
        .marker(Marker::new().color(NamedColor::Pink));
    let mut plot = Plot::new();

    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Overlaid Histogram

#![allow(unused)]
fn main() {
fn overlaid_histogram(show: bool) -> Plot {
    let samples1 = sample_normal_distribution(500, 0.0, 1.0);
    let trace1 = Histogram::new(samples1)
        .name("trace 1")
        .opacity(0.5)
        .marker(Marker::new().color(NamedColor::Green));

    let samples2 = sample_normal_distribution(500, 0.0, 1.0);
    let trace2 = Histogram::new(samples2)
        .name("trace 2")
        .opacity(0.6)
        .marker(Marker::new().color(NamedColor::Red));

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    let layout = Layout::new().bar_mode(BarMode::Overlay);
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Stacked Histograms

#![allow(unused)]
fn main() {
fn stacked_histograms(show: bool) -> Plot {
    let samples1 = sample_normal_distribution(500, 0.0, 1.0);
    let trace1 = Histogram::new(samples1)
        .name("trace 1")
        .opacity(0.5)
        .marker(Marker::new().color(NamedColor::Green));

    let samples2 = sample_normal_distribution(500, 0.0, 1.0);
    let trace2 = Histogram::new(samples2)
        .name("trace 2")
        .opacity(0.6)
        .marker(Marker::new().color(NamedColor::Red));

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    let layout = Layout::new().bar_mode(BarMode::Stack);
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Colored and Styled Histograms

#![allow(unused)]
fn main() {
fn colored_and_styled_histograms(show: bool) -> Plot {
    let n = 500;
    let x1 = sample_uniform_distribution(n, 0.0, 5.0);
    let x2 = sample_uniform_distribution(n, 0.0, 10.0);
    let y1 = sample_uniform_distribution(n, 0.0, 1.0);
    let y2 = sample_uniform_distribution(n, 0.0, 2.0);

    let trace1 = Histogram::new_xy(x1, y1)
        .name("control")
        .hist_func(HistFunc::Count)
        .marker(
            Marker::new()
                .color(Rgba::new(255, 100, 102, 0.7))
                .line(Line::new().color(Rgba::new(255, 100, 102, 1.0)).width(1.0)),
        )
        .opacity(0.5)
        .auto_bin_x(false)
        .x_bins(Bins::new(0.5, 2.8, 0.06));
    let trace2 = Histogram::new_xy(x2, y2)
        .name("experimental")
        .hist_func(HistFunc::Count)
        .marker(
            Marker::new()
                .color(Rgba::new(100, 200, 102, 0.7))
                .line(Line::new().color(Rgba::new(100, 200, 102, 1.0)).width(1.0)),
        )
        .opacity(0.75)
        .auto_bin_x(false)
        .x_bins(Bins::new(-3.2, 4.0, 0.06));
    let layout = Layout::new()
        .title("Colored and Styled Histograms")
        .x_axis(Axis::new().title("Value"))
        .y_axis(Axis::new().title("Count"))
        .bar_mode(BarMode::Overlay)
        .bar_gap(0.05)
        .bar_group_gap(0.2);

    let mut plot = Plot::new();
    plot.set_layout(layout);
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    if show {
        plot.show();
    }
    plot
}
}

Cumulative Histogram

#![allow(unused)]
fn main() {
fn cumulative_histogram(show: bool) -> Plot {
    let n = 500;
    let x = sample_uniform_distribution(n, 0.0, 1.0);
    let trace = Histogram::new(x)
        .cumulative(Cumulative::new().enabled(true))
        .marker(Marker::new().color(NamedColor::BurlyWood));
    let mut plot = Plot::new();
    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Normalized Histogram

#![allow(unused)]
fn main() {
fn normalized_histogram(show: bool) -> Plot {
    let n = 500;
    let x = sample_uniform_distribution(n, 0.0, 1.0);
    let trace = Histogram::new(x)
        .hist_norm(HistNorm::Probability)
        .marker(Marker::new().color(NamedColor::SeaGreen));
    let mut plot = Plot::new();
    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Specify Binning Function

#![allow(unused)]
fn main() {
fn specify_binning_function(show: bool) -> Plot {
    let x = vec!["Apples", "Apples", "Apples", "Oranges", "Bananas"];
    let y = vec!["5", "10", "3", "10", "5"];

    let trace1 = Histogram::new_xy(x.clone(), y.clone())
        .name("count")
        .hist_func(HistFunc::Count);
    let trace2 = Histogram::new_xy(x.clone(), y.clone())
        .name("sum")
        .hist_func(HistFunc::Sum);

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    if show {
        plot.show();
    }
    plot
}
}

Scientific Charts

The source code for the following examples can also be found here.

KindLink
Contour PlotsContour Plots
HeatmapsHeatmaps

Contour Plots

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use plotly::common::{ColorScale, ColorScalePalette, Title};
use plotly::contour::Contours;
use plotly::{Contour, HeatMap, Layout, Plot};
use std::f64::consts::PI;
}

The to_inline_html method is used to produce the html plot displayed in this page.

Simple Contour Plot

#![allow(unused)]
fn main() {
fn simple_contour_plot(show: bool) -> Plot {
    let n = 200;
    let mut x = Vec::<f64>::new();
    let mut y = Vec::<f64>::new();
    let mut z: Vec<Vec<f64>> = Vec::new();

    for index in 0..n {
        let value = -2.0 * PI + 4.0 * PI * (index as f64) / (n as f64);
        x.push(value);
        y.push(value);
    }

    y.iter().take(n).for_each(|y| {
        let mut row = Vec::<f64>::new();
        x.iter().take(n).for_each(|x| {
            let radius_squared = x.powf(2.0) + y.powf(2.0);
            let zv = x.sin() * y.cos() * radius_squared.sin() / (radius_squared + 1.0).log10();
            row.push(zv);
        });
        z.push(row);
    });

    let trace = Contour::new(x, y, z);
    let mut plot = Plot::new();

    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Colorscale for Contour Plot

#![allow(unused)]
fn main() {
fn colorscale_for_contour_plot(show: bool) -> Plot {
    let z = vec![
        vec![10.0, 10.625, 12.5, 15.625, 20.0],
        vec![5.625, 6.25, 8.125, 11.25, 15.625],
        vec![2.5, 3.125, 5., 8.125, 12.5],
        vec![0.625, 1.25, 3.125, 6.25, 10.625],
        vec![0.0, 0.625, 2.5, 5.625, 10.0],
    ];
    let trace = Contour::new_z(z).color_scale(ColorScale::Palette(ColorScalePalette::Jet));

    let layout = Layout::new().title("Colorscale for Contour Plot");
    let mut plot = Plot::new();
    plot.set_layout(layout);
    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Customizing Size and Range of a Contour Plot Contours

#![allow(unused)]
fn main() {
fn customizing_size_and_range_of_a_contour_plots_contours(show: bool) -> Plot {
    let z = vec![
        vec![10.0, 10.625, 12.5, 15.625, 20.0],
        vec![5.625, 6.25, 8.125, 11.25, 15.625],
        vec![2.5, 3.125, 5., 8.125, 12.5],
        vec![0.625, 1.25, 3.125, 6.25, 10.625],
        vec![0.0, 0.625, 2.5, 5.625, 10.0],
    ];
    let trace = Contour::new_z(z)
        .color_scale(ColorScale::Palette(ColorScalePalette::Jet))
        .auto_contour(false)
        .contours(Contours::new().start(0.0).end(8.0).size(2.0));

    let layout = Layout::new().title("Customizing Size and Range of Contours");
    let mut plot = Plot::new();
    plot.set_layout(layout);
    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Customizing Spacing Between X and Y Ticks

#![allow(unused)]
fn main() {
fn customizing_spacing_between_x_and_y_ticks(show: bool) -> Plot {
    let z = vec![
        vec![10.0, 10.625, 12.5, 15.625, 20.0],
        vec![5.625, 6.25, 8.125, 11.25, 15.625],
        vec![2.5, 3.125, 5., 8.125, 12.5],
        vec![0.625, 1.25, 3.125, 6.25, 10.625],
        vec![0.0, 0.625, 2.5, 5.625, 10.0],
    ];
    let trace = Contour::new_z(z)
        .color_scale(ColorScale::Palette(ColorScalePalette::Jet))
        .dx(10.0)
        .x0(5.0)
        .dy(10.0)
        .y0(10.0);

    let layout = Layout::new().title("Customizing Size and Range of Contours");
    let mut plot = Plot::new();
    plot.set_layout(layout);
    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Heatmaps

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use plotly::common::{ColorScale, ColorScalePalette, Title};
use plotly::contour::Contours;
use plotly::{Contour, HeatMap, Layout, Plot};
use std::f64::consts::PI;
}

The to_inline_html method is used to produce the html plot displayed in this page.

Basic Heatmap

#![allow(unused)]
fn main() {
fn basic_heat_map(show: bool) -> Plot {
    let z = vec![vec![1, 20, 30], vec![20, 1, 60], vec![30, 60, 1]];
    let trace = HeatMap::new_z(z).zmin(1.0).zmax(60.0);
    let mut plot = Plot::new();
    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Financial Charts

The source code for the following examples can also be found here.

KindLink
Time Series and Date AxesTime Series and Date Axes
Candlestick ChartsCandlestick Charts
OHLC ChartsOHLC Charts

Time Series and Date Axes

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use plotly::common::{TickFormatStop, Title};
use plotly::layout::{Axis, RangeSelector, RangeSlider, SelectorButton, SelectorStep, StepMode};
use plotly::{Candlestick, Layout, Ohlc, Plot, Scatter};
use serde::Deserialize;
use std::env;
use std::path::PathBuf;
}

The to_inline_html method is used to produce the html plot displayed in this page.

Time Series Plot with Custom Date Range

#![allow(unused)]
fn main() {
fn time_series_plot_with_custom_date_range(show: bool) -> Plot {
    let data = load_apple_data();
    let date: Vec<String> = data.iter().map(|d| d.date.clone()).collect();
    let high: Vec<f64> = data.iter().map(|d| d.high).collect();

    let trace = Scatter::new(date, high);

    let mut plot = Plot::new();
    plot.add_trace(trace);

    let layout = Layout::new()
        .x_axis(Axis::new().range(vec!["2016-07-01", "2016-12-31"]))
        .title("Manually Set Date Range");
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Time Series with Range Slider

#![allow(unused)]
fn main() {
fn time_series_with_range_slider(show: bool) -> Plot {
    let data = load_apple_data();
    let date: Vec<String> = data.iter().map(|d| d.date.clone()).collect();
    let high: Vec<f64> = data.iter().map(|d| d.high).collect();

    let trace = Scatter::new(date, high);

    let mut plot = Plot::new();
    plot.add_trace(trace);

    let layout = Layout::new()
        .x_axis(Axis::new().range_slider(RangeSlider::new().visible(true)))
        .title("Manually Set Date Range");
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Time Series with Range Selector Buttons

#![allow(unused)]
fn main() {
fn time_series_with_range_selector_buttons(show: bool) -> Plot {
    let data = load_apple_data();
    let date: Vec<String> = data.iter().map(|d| d.date.clone()).collect();
    let high: Vec<f64> = data.iter().map(|d| d.high).collect();

    let trace = Scatter::new(date, high);

    let mut plot = Plot::new();
    plot.add_trace(trace);

    let layout = Layout::new().x_axis(
        Axis::new()
            .range_slider(RangeSlider::new().visible(true))
            .range_selector(RangeSelector::new().buttons(vec![
                        SelectorButton::new()
                            .count(1)
                            .label("1m")
                            .step(SelectorStep::Month)
                            .step_mode(StepMode::Backward),
                        SelectorButton::new()
                            .count(6)
                            .label("6m")
                            .step(SelectorStep::Month)
                            .step_mode(StepMode::Backward),
                        SelectorButton::new()
                            .count(1)
                            .label("YTD")
                            .step(SelectorStep::Year)
                            .step_mode(StepMode::ToDate),
                        SelectorButton::new()
                            .count(1)
                            .label("1y")
                            .step(SelectorStep::Year)
                            .step_mode(StepMode::Backward),
                        SelectorButton::new().step(SelectorStep::All),
                    ])),
    );
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Customizing Tick Label Formatting by Zoom Level

#![allow(unused)]
fn main() {
fn customizing_tick_label_formatting_by_zoom_level(show: bool) -> Plot {
    let data = load_apple_data();
    let date: Vec<String> = data.iter().map(|d| d.date.clone()).collect();
    let high: Vec<f64> = data.iter().map(|d| d.high).collect();

    let trace = Scatter::new(date, high);

    let mut plot = Plot::new();
    plot.add_trace(trace);

    let layout = Layout::new().x_axis(
        Axis::new()
            .range_slider(RangeSlider::new().visible(true))
            .tick_format_stops(vec![
                TickFormatStop::new()
                    .dtick_range(vec![0, 1000])
                    .value("%H:%M:%S.%L ms"),
                TickFormatStop::new()
                    .dtick_range(vec![1000, 60000])
                    .value("%H:%M:%S s"),
                TickFormatStop::new()
                    .dtick_range(vec![60000, 3600000])
                    .value("%H:%M m"),
                TickFormatStop::new()
                    .dtick_range(vec![3600000, 86400000])
                    .value("%H:%M h"),
                TickFormatStop::new()
                    .dtick_range(vec![86400000, 604800000])
                    .value("%e. %b d"),
                TickFormatStop::new()
                    .dtick_range(vec!["M1", "M12"])
                    .value("%b '%y M"),
            ]),
    );
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Candlestick Charts

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use plotly::common::{TickFormatStop, Title};
use plotly::layout::{Axis, RangeSelector, RangeSlider, SelectorButton, SelectorStep, StepMode};
use plotly::{Candlestick, Layout, Ohlc, Plot, Scatter};
use serde::Deserialize;
use std::env;
use std::path::PathBuf;
}

The to_inline_html method is used to produce the html plot displayed in this page.

Simple Candlestick Chart

#![allow(unused)]
fn main() {
fn simple_candlestick_chart(show: bool) -> Plot {
    let x = vec![
        "2017-01-04",
        "2017-01-05",
        "2017-01-06",
        "2017-01-09",
        "2017-01-10",
        "2017-01-11",
        "2017-01-12",
        "2017-01-13",
        "2017-01-17",
        "2017-01-18",
        "2017-01-19",
        "2017-01-20",
        "2017-01-23",
        "2017-01-24",
        "2017-01-25",
        "2017-01-26",
        "2017-01-27",
        "2017-01-30",
        "2017-01-31",
        "2017-02-01",
        "2017-02-02",
        "2017-02-03",
        "2017-02-06",
        "2017-02-07",
        "2017-02-08",
        "2017-02-09",
        "2017-02-10",
        "2017-02-13",
        "2017-02-14",
        "2017-02-15",
    ];
    let open = vec![
        115.849998, 115.919998, 116.779999, 117.949997, 118.769997, 118.739998, 118.900002,
        119.110001, 118.339996, 120.0, 119.400002, 120.449997, 120.0, 119.550003, 120.419998,
        121.669998, 122.139999, 120.93, 121.150002, 127.029999, 127.980003, 128.309998, 129.130005,
        130.539993, 131.350006, 131.649994, 132.460007, 133.080002, 133.470001, 135.520004,
    ];
    let high = vec![
        116.510002, 116.860001, 118.160004, 119.43, 119.379997, 119.93, 119.300003, 119.620003,
        120.239998, 120.5, 120.089996, 120.449997, 120.809998, 120.099998, 122.099998, 122.440002,
        122.349998, 121.629997, 121.389999, 130.490005, 129.389999, 129.190002, 130.5, 132.089996,
        132.220001, 132.449997, 132.940002, 133.820007, 135.089996, 136.270004,
    ];
    let low = vec![
        115.75, 115.809998, 116.470001, 117.940002, 118.300003, 118.599998, 118.209999, 118.809998,
        118.220001, 119.709999, 119.370003, 119.730003, 119.769997, 119.5, 120.279999, 121.599998,
        121.599998, 120.660004, 120.620003, 127.010002, 127.779999, 128.160004, 128.899994,
        130.449997, 131.220001, 131.119995, 132.050003, 132.75, 133.25, 134.619995,
    ];
    let close = vec![
        116.019997, 116.610001, 117.910004, 118.989998, 119.110001, 119.75, 119.25, 119.040001,
        120.0, 119.989998, 119.779999, 120.0, 120.080002, 119.970001, 121.879997, 121.940002,
        121.949997, 121.629997, 121.349998, 128.75, 128.529999, 129.080002, 130.289993, 131.529999,
        132.039993, 132.419998, 132.119995, 133.289993, 135.020004, 135.509995,
    ];

    let trace1 = Candlestick::new(x, open, high, low, close);

    let mut plot = Plot::new();
    plot.add_trace(trace1);

    if show {
        plot.show();
    }
    plot
}
}

OHLC Charts

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use plotly::common::{TickFormatStop, Title};
use plotly::layout::{Axis, RangeSelector, RangeSlider, SelectorButton, SelectorStep, StepMode};
use plotly::{Candlestick, Layout, Ohlc, Plot, Scatter};
use serde::Deserialize;
use std::env;
use std::path::PathBuf;
}

The to_inline_html method is used to produce the html plot displayed in this page.

Simple OHLC Chart

#![allow(unused)]
fn main() {
fn simple_ohlc_chart(show: bool) -> Plot {
    let x = vec![
        "2017-01-04",
        "2017-01-05",
        "2017-01-06",
        "2017-01-09",
        "2017-01-10",
        "2017-01-11",
        "2017-01-12",
        "2017-01-13",
        "2017-01-17",
        "2017-01-18",
        "2017-01-19",
        "2017-01-20",
        "2017-01-23",
        "2017-01-24",
        "2017-01-25",
        "2017-01-26",
        "2017-01-27",
        "2017-01-30",
        "2017-01-31",
        "2017-02-01",
        "2017-02-02",
        "2017-02-03",
        "2017-02-06",
        "2017-02-07",
        "2017-02-08",
        "2017-02-09",
        "2017-02-10",
        "2017-02-13",
        "2017-02-14",
        "2017-02-15",
    ];
    let open = vec![
        115.849998, 115.919998, 116.779999, 117.949997, 118.769997, 118.739998, 118.900002,
        119.110001, 118.339996, 120.0, 119.400002, 120.449997, 120.0, 119.550003, 120.419998,
        121.669998, 122.139999, 120.93, 121.150002, 127.029999, 127.980003, 128.309998, 129.130005,
        130.539993, 131.350006, 131.649994, 132.460007, 133.080002, 133.470001, 135.520004,
    ];
    let high = vec![
        116.510002, 116.860001, 118.160004, 119.43, 119.379997, 119.93, 119.300003, 119.620003,
        120.239998, 120.5, 120.089996, 120.449997, 120.809998, 120.099998, 122.099998, 122.440002,
        122.349998, 121.629997, 121.389999, 130.490005, 129.389999, 129.190002, 130.5, 132.089996,
        132.220001, 132.449997, 132.940002, 133.820007, 135.089996, 136.270004,
    ];
    let low = vec![
        115.75, 115.809998, 116.470001, 117.940002, 118.300003, 118.599998, 118.209999, 118.809998,
        118.220001, 119.709999, 119.370003, 119.730003, 119.769997, 119.5, 120.279999, 121.599998,
        121.599998, 120.660004, 120.620003, 127.010002, 127.779999, 128.160004, 128.899994,
        130.449997, 131.220001, 131.119995, 132.050003, 132.75, 133.25, 134.619995,
    ];
    let close = vec![
        116.019997, 116.610001, 117.910004, 118.989998, 119.110001, 119.75, 119.25, 119.040001,
        120.0, 119.989998, 119.779999, 120.0, 120.080002, 119.970001, 121.879997, 121.940002,
        121.949997, 121.629997, 121.349998, 128.75, 128.529999, 129.080002, 130.289993, 131.529999,
        132.039993, 132.419998, 132.119995, 133.289993, 135.020004, 135.509995,
    ];

    let trace1 = Ohlc::new(x, open, high, low, close);

    let mut plot = Plot::new();
    plot.add_trace(trace1);

    if show {
        plot.show();
    }
    plot
}
}

3D Charts

The complete source code for the following examples can also be found here.

KindLink
Scatter3DScatter 3D Charts

Scatter 3D Charts

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use ndarray::Array;
use plotly::common::{
    ColorScale, ColorScalePalette, DashType, Fill, Font, Line, LineShape, Marker, Mode, Title,
};
use plotly::layout::{Axis, BarMode, Layout, Legend, TicksDirection};
use plotly::Sankey;
use rand_distr::{Distribution, Normal, Uniform};
}

The to_inline_html method is used to produce the html plot displayed in this page.

Constructing a basic Scatter 3D plot

#![allow(unused)]
fn main() {
fn simple_scatter3d_plot(show: bool) -> Plot {
    let n: usize = 100;
    let t: Vec<f64> = Array::linspace(0., 10., n).into_raw_vec_and_offset().0;
    let y: Vec<f64> = t.iter().map(|x| x.sin()).collect();
    let z: Vec<f64> = t.iter().map(|x| x.cos()).collect();

    let trace = Scatter3D::new(t, y, z).mode(Mode::Markers);
    let mut plot = Plot::new();
    plot.add_trace(trace);

    if show {
        plot.show();
    }
    plot
}
}

Subplots

The complete source code for the following examples can also be found here.

KindLink
SubplotsScatter Plots
Multiple AxesLine Charts

Subplots

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use plotly::common::{Font, Side, Title};
use plotly::layout::{Axis, GridPattern, Layout, LayoutGrid, Legend, RowOrder};
use plotly::{Plot, Rgb, Scatter};
}

The to_inline_html method is used to produce the html plot displayed in this page.

Simple Subplot

#![allow(unused)]
fn main() {
fn simple_subplot(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1");
    let trace2 = Scatter::new(vec![20, 30, 40], vec![50, 60, 70])
        .name("trace2")
        .x_axis("x2")
        .y_axis("y2");

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    let layout = Layout::new().grid(
        LayoutGrid::new()
            .rows(1)
            .columns(2)
            .pattern(GridPattern::Independent),
    );
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Custom Sized Subplot

#![allow(unused)]
fn main() {
fn custom_sized_subplot(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1");
    let trace2 = Scatter::new(vec![20, 30, 40], vec![50, 60, 70])
        .name("trace2")
        .x_axis("x2")
        .y_axis("y2");

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    let layout = Layout::new()
        .x_axis(Axis::new().domain(&[0., 0.7]))
        .y_axis2(Axis::new().anchor("x2"))
        .x_axis2(Axis::new().domain(&[0.8, 1.]));
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Multiple Subplots

#![allow(unused)]
fn main() {
fn multiple_subplots(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1");
    let trace2 = Scatter::new(vec![20, 30, 40], vec![50, 60, 70])
        .name("trace2")
        .x_axis("x2")
        .y_axis("y2");
    let trace3 = Scatter::new(vec![300, 400, 500], vec![600, 700, 800])
        .x_axis("x3")
        .y_axis("y3");
    let trace4 = Scatter::new(vec![4000, 5000, 6000], vec![7000, 8000, 9000])
        .x_axis("x4")
        .y_axis("y4");

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);
    plot.add_trace(trace4);

    let layout = Layout::new().grid(
        LayoutGrid::new()
            .rows(2)
            .columns(2)
            .pattern(GridPattern::Independent),
    );
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Stacked Subplots

#![allow(unused)]
fn main() {
fn stacked_subplots(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![0, 1, 2], vec![10, 11, 12]).name("trace1");
    let trace2 = Scatter::new(vec![2, 3, 4], vec![100, 110, 120])
        .name("trace2")
        .x_axis("x2")
        .y_axis("y2");
    let trace3 = Scatter::new(vec![3, 4, 5], vec![1000, 1100, 1200])
        .x_axis("x3")
        .y_axis("y3");

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);

    let layout = Layout::new().grid(
        LayoutGrid::new()
            .rows(3)
            .columns(1)
            .pattern(GridPattern::Independent)
            .row_order(RowOrder::BottomToTop),
    );
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Stacked Subplots with Shared X Axis

#![allow(unused)]
fn main() {
fn stacked_subplots_with_shared_x_axis(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![0, 1, 2], vec![10, 11, 12]).name("trace1");
    let trace2 = Scatter::new(vec![2, 3, 4], vec![100, 110, 120])
        .name("trace2")
        .y_axis("y2");
    let trace3 = Scatter::new(vec![3, 4, 5], vec![1000, 1100, 1200]).y_axis("y3");

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);

    let layout = Layout::new()
        .y_axis(Axis::new().domain(&[0., 0.33]))
        .legend(Legend::new().trace_order(TraceOrder::Reversed))
        .y_axis2(Axis::new().domain(&[0.33, 0.66]))
        .y_axis3(Axis::new().domain(&[0.66, 1.]));
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Multiple Custom Sized Subplots

#![allow(unused)]
fn main() {
fn multiple_custom_sized_subplots(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2], vec![1, 2]).name("(1,1)");
    let trace2 = Scatter::new(vec![1, 2], vec![1, 2])
        .name("(1,2,1)")
        .x_axis("x2")
        .y_axis("y2");
    let trace3 = Scatter::new(vec![1, 2], vec![1, 2])
        .name("(1,2,2)")
        .x_axis("x3")
        .y_axis("y3");
    let trace4 = Scatter::new(vec![1, 2], vec![1, 2])
        .name("{(2,1), (2,2)}")
        .x_axis("x4")
        .y_axis("y4");

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);
    plot.add_trace(trace4);

    let layout = Layout::new()
        .title("Multiple Custom Sized Subplots")
        .x_axis(Axis::new().domain(&[0., 0.45]).anchor("y1"))
        .y_axis(Axis::new().domain(&[0.5, 1.]).anchor("x1"))
        .x_axis2(Axis::new().domain(&[0.55, 1.]).anchor("y2"))
        .y_axis2(Axis::new().domain(&[0.8, 1.]).anchor("x2"))
        .x_axis3(Axis::new().domain(&[0.55, 1.]).anchor("y3"))
        .y_axis3(Axis::new().domain(&[0.5, 0.75]).anchor("x3"))
        .x_axis4(Axis::new().domain(&[0., 1.]).anchor("y4"))
        .y_axis4(Axis::new().domain(&[0., 0.45]).anchor("x4"));
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Multiple Axes

The following imports have been used to produce the plots below:

#![allow(unused)]
fn main() {
use plotly::common::{Font, AxisSide, Title};
use plotly::layout::{Axis, GridPattern, Layout, LayoutGrid, Legend, RowOrder};
use plotly::{Plot, Rgb, Scatter};
}

The to_inline_html method is used to produce the html plot displayed in this page.

Two Y Axes

#![allow(unused)]
fn main() {
fn two_y_axes(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3], vec![40, 50, 60]).name("trace1");
    let trace2 = Scatter::new(vec![2, 3, 4], vec![4, 5, 6])
        .name("trace2")
        .y_axis("y2");

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);

    let layout = Layout::new()
        .title("Double Y Axis Example")
        .y_axis(Axis::new().title("yaxis title"))
        .y_axis2(
            Axis::new()
                .title(Title::from("yaxis2 title").font(Font::new().color(Rgb::new(148, 103, 189))))
                .tick_font(Font::new().color(Rgb::new(148, 103, 189)))
                .overlaying("y")
                .side(AxisSide::Right),
        );
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}

Multiple Axes

#![allow(unused)]
fn main() {
fn multiple_axes(show: bool) -> Plot {
    let trace1 = Scatter::new(vec![1, 2, 3], vec![4, 5, 6]).name("trace1");
    let trace2 = Scatter::new(vec![2, 3, 4], vec![40, 50, 60])
        .name("trace2")
        .y_axis("y2");
    let trace3 = Scatter::new(vec![4, 5, 6], vec![40_000, 50_000, 60_000]).y_axis("y3");
    let trace4 = Scatter::new(vec![5, 6, 7], vec![400_000, 500_000, 600_000]).y_axis("y4");

    let mut plot = Plot::new();
    plot.add_trace(trace1);
    plot.add_trace(trace2);
    plot.add_trace(trace3);
    plot.add_trace(trace4);

    let layout = Layout::new()
        .title("multiple y-axes example")
        .width(800)
        .x_axis(Axis::new().domain(&[0.3, 0.7]))
        .y_axis(
            Axis::new()
                .title(Title::from("yaxis title").font(Font::new().color("#1f77b4")))
                .tick_font(Font::new().color("#1f77b4")),
        )
        .y_axis2(
            Axis::new()
                .title(Title::from("yaxis2 title").font(Font::new().color("#ff7f0e")))
                .tick_font(Font::new().color("#ff7f0e"))
                .anchor("free")
                .overlaying("y")
                .side(AxisSide::Left)
                .position(0.15),
        )
        .y_axis3(
            Axis::new()
                .title(Title::from("yaxis3 title").font(Font::new().color("#d62728")))
                .tick_font(Font::new().color("#d62728"))
                .anchor("x")
                .overlaying("y")
                .side(AxisSide::Right),
        )
        .y_axis4(
            Axis::new()
                .title(Title::from("yaxis4 title").font(Font::new().color("#9467bd")))
                .tick_font(Font::new().color("#9467bd"))
                .anchor("free")
                .overlaying("y")
                .side(AxisSide::Right)
                .position(0.85),
        );
    plot.set_layout(layout);

    if show {
        plot.show();
    }
    plot
}
}