<a href="https://crates.io/crates/plotlars">
<img alt="Crates.io" src="https://img.shields.io/crates/v/plotlars.svg"></a>
<a href="https://docs.rs/plotlars">
<img alt="docs.rs" src="https://img.shields.io/docsrs/plotlars">
</a>
<a href="https://crates.io/crates/plotlars">
<img alt="Downloads" src="https://img.shields.io/crates/d/plotlars">
</a>
<a href="https://github.com/alceal/plotlars/blob/main/LICENSE">
<img alt="License" src="https://img.shields.io/badge/license-MIT-blue.svg">
</a>
Plotlars is a versatile Rust library that bridges the gap between the powerful Polars data analysis library and visualization backends. It supports two rendering backends: Plotly for interactive HTML-based charts and Plotters for static image output (PNG/SVG). Plotlars simplifies the process of creating visualizations from data frames, allowing developers to focus on data insights rather than the intricacies of plot creation.
| Plot Type | Required Params | Facet | Group | Plotly | Plotters |
|---|---|---|---|---|---|
| Array2dPlot | data | -- | -- | Yes | -- |
| BarPlot | data, labels, values | Yes | Yes | Yes | Yes |
| BoxPlot | data, labels, values | Yes | Yes | Yes | Yes |
| CandlestickPlot | data, dates, open, high, low, close | -- | -- | Yes | Yes |
| ContourPlot | data, x, y, z | Yes | -- | Yes | -- |
| DensityMapbox | data, lat, lon, z | -- | -- | Yes | -- |
| HeatMap | data, x, y, z | Yes | -- | Yes | Yes |
| Histogram | data, x | Yes | Yes | Yes | Yes |
| Image | path | -- | -- | Yes | -- |
| LinePlot | data, x, y | Yes | -- | Yes | Yes |
| Mesh3D | data, x, y, z | Yes | -- | Yes | -- |
| OhlcPlot | data, dates, open, high, low, close | -- | -- | Yes | -- |
| PieChart | data, labels | Yes | -- | Yes | -- |
| SankeyDiagram | data, sources, targets, values | Yes | -- | Yes | -- |
| Scatter3dPlot | data, x, y, z | Yes | Yes | Yes | -- |
| ScatterGeo | data, lat, lon | -- | Yes | Yes | -- |
| ScatterMap | data, latitude, longitude | -- | Yes | Yes | -- |
| ScatterPlot | data, x, y | Yes | Yes | Yes | Yes |
| ScatterPolar | data, theta, r | Yes | Yes | Yes | -- |
| SubplotGrid | plots | -- | -- | Yes | -- |
| SurfacePlot | data, x, y, z | Yes | -- | Yes | -- |
| Table | data, columns | -- | -- | Yes | -- |
| TimeSeriesPlot | data, x, y | Yes | -- | Yes | Yes |
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 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(PlRefPath::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::{
CsvReader,
ScatterPlot,
Plot,
Rgb,
polars::prelude::*,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let dataset = CsvReader::new("data/penguins.csv")
.finish()?
.lazy()
.select([
col("species"),
col("flipper_length_mm").cast(DataType::Int16),
col("body_mass_g").cast(DataType::Int16),
])
.collect()?;
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();
Ok(())
}
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.
Plotlars requires exactly one backend feature to be enabled:
# Interactive HTML charts (Plotly)
cargo add plotlars --features plotly
# Static image output (Plotters)
cargo add plotlars --features plotters
Optional features for file loading:
# JSON file support
cargo add plotlars --features plotly,format-json
# Excel file support
cargo add plotlars --features plotly,format-excel
Tip: You don't need to add
polarsto your ownCargo.toml— plotlars re-exports a matching version, so you can import it viause plotlars::polars::prelude::*;. If you do depend onpolarsdirectly, pin it to the same version plotlars uses (currently0.54) to avoid dependency-resolution conflicts.
Plotlars comes with several ready-to-use demo programs. Examples are prefixed by
backend (plotly_ or `plot
$ claude mcp add plotlars \
-- python -m otcore.mcp_server <graph>