Plotlars is a versatile Rust library that acts as a wrapper around the Plotly crate, bridging the gap between the powerful Polars data analysis library and Plotly. It simplifies the process of creating visualizations from data frames, allowing developers to focus on data insights rather than the intricacies of plot creation.
The creation of Plotlars was driven by the need to simplify the process of creating complex plots in Rust, particularly when working with the powerful Polars data manipulation library. Generating visualizations often requires extensive boilerplate code and deep knowledge of both the plotting library (Plotly) and the data structure. This complexity can be a significant hurdle, especially for users who need to focus on analyzing and interpreting data rather than wrestling with intricate plotting logic.
To illustrate this, consider the following example where a scatter plot is created without Plotlars:
use plotly::{
common::*,
layout::*,
Plot,
Scatter,
};
use polars::prelude::*;
fn main() {
let dataset = LazyCsvReader::new(PlPath::new("data/penguins.csv"))
.finish().unwrap()
.select([
col("species"),
col("flipper_length_mm").cast(DataType::Int16),
col("body_mass_g").cast(DataType::Int16),
])
.collect().unwrap();
let group_column = "species";
let x = "body_mass_g";
let y = "flipper_length_mm";
let groups = dataset
.column(group_column).unwrap()
.unique().unwrap();
let layout = Layout::new()
.title(Title::with_text("Penguin Flipper Length vs Body Mass"))
.x_axis(Axis::new().title(Title::with_text("Body Mass (g)")))
.y_axis(Axis::new().title(Title::with_text("Flipper Length (mm)")))
.legend(Legend::new().title(Title::with_text("Species")));
let mut plot = Plot::new();
plot.set_layout(layout);
let groups_str = groups.str().unwrap();
for group in groups_str.into_iter() {
let group = group.unwrap();
let data = dataset
.clone()
.lazy()
.filter(col(group_column).eq(lit(group)))
.collect().unwrap();
let x = data
.column(x).unwrap()
.i16().unwrap()
.to_vec();
let y = data
.column(y).unwrap()
.i16().unwrap()
.to_vec();
let trace = Scatter::default()
.x(x)
.y(y)
.name(group)
.mode(Mode::Markers)
.marker(Marker::new().size(10).opacity(0.5));
plot.add_trace(trace);
}
plot.show();
}In this example, creating a scatter plot involves writing substantial code to manually handle the data and configure the plot, including grouping the data by category and setting up the plot layout.
Now, compare that to the same plot created using Plotlars:
use plotlars::{
ScatterPlot,
Plot,
Rgb,
};
use polars::prelude::*;
fn main() {
let dataset = LazyCsvReader::new(PlPath::new("data/penguins.csv"))
.finish().unwrap()
.select([
col("species"),
col("flipper_length_mm").cast(DataType::Int16),
col("body_mass_g").cast(DataType::Int16),
])
.collect().unwrap();
ScatterPlot::builder()
.data(&dataset)
.x("body_mass_g")
.y("flipper_length_mm")
.group("species")
.opacity(0.5)
.size(12)
.colors(vec![
Rgb(178, 34, 34),
Rgb(65, 105, 225),
Rgb(255, 140, 0),
])
.plot_title("Penguin Flipper Length vs Body Mass")
.x_title("Body Mass (g)")
.y_title("Flipper Length (mm)")
.legend_title("Species")
.build()
.plot();
}This is the output:
With Plotlars, the same scatter plot is created with significantly less code. The library abstracts away the complexities of dealing with individual plot components and allows the user to specify high-level plot characteristics. This streamlined approach not only saves time but also reduces the potential for errors and makes the code more readable and maintainable.
cargo add plotlarsPlotlars comes with several ready‑to‑use demo programs in the examples/ directory.
You can build and execute any of them with Cargo’s --example flag:
cargo run --example barplotReplace barplot with the file name (without the .rs extension) of the example you want to run.
- Seamless Integration with Polars: Leverage the power of Polars for efficient data manipulation and analysis.
- Support for Multiple Plot Types: Easily create bar, line, scatter, and other plot types.
- Customization: Modify plot appearance with an intuitive API.
Plotlars supports exporting plots to static image files in various formats (PNG, JPG, WEBP, SVG) through the write_image method.
To use image export functionality, you need to enable one of the export features and have the corresponding WebDriver installed:
-
Default (recommended - uses any available driver):
cargo add plotlars --features export-default
-
Chrome/Chromium:
cargo add plotlars --features export-chrome
Install ChromeDriver: https://chromedriver.chromium.org/
-
Firefox:
cargo add plotlars --features export-firefox
Install GeckoDriver: https://github.com/mozilla/geckodriver/releases
use plotlars::{ScatterPlot, Plot};
use polars::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let dataset = LazyCsvReader::new(PlPath::new("data/penguins.csv"))
.finish()?
.collect()?;
let plot = ScatterPlot::builder()
.data(&dataset)
.x("body_mass_g")
.y("flipper_length_mm")
.plot_title("Penguin Data")
.build();
// Export as PNG (1200x800 pixels, 2x scale for high DPI)
plot.write_image("output.png", 1200, 800, 2.0)?;
Ok(())
}Plotlars seamlessly integrates with Jupyter Notebooks, allowing you to leverage the power of interactive data visualization directly within your notebook environment. This integration is made possible through the use of the evcxr project, which provides a Jupyter kernel for the Rust programming language.
With Polars, evcxr, and Plotlars, data science in Rust leaps to the next level , making powerful data analysis and visualization more accessible and efficient than ever before.
This project is licensed under the MIT License. See the LICENSE.txt file for details.

























