MCPcopy Index your code
hub / github.com/alceal/plotlars

github.com/alceal/plotlars @v0.12.6

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.12.6 ↗ · + Follow
1,147 symbols 3,574 edges 130 files 184 documented · 16%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Plotlars

<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.

Implemented Plots Overview

Array 2D Bar Plot Box Plot Candlestick
Contour Plot Density Mapbox Heat Map Histogram
Image Line Plot Mesh3D OHLC
Pie Chart Sankey Diagram Scatter 3D Plot Scatter Geo
Scatter Map Scatter Plot Scatter Polar Subplot Grid Irregular
Subplot Grid Regular Surface Plot Table Time Series

Plot Types Reference

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

Motivation

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:

Plot example

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.

Installation

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 polars to your own Cargo.toml — plotlars re-exports a matching version, so you can import it via use plotlars::polars::prelude::*;. If you do depend on polars directly, pin it to the same version plotlars uses (currently 0.54) to avoid dependency-resolution conflicts.

Running the examples

Plotlars comes with several ready-to-use demo programs. Examples are prefixed by backend (plotly_ or `plot

Extension points exported contracts — how you extend this code

Plot (Interface)
Core trait implemented by all plot types. Provides access to the intermediate representation (IR) data. [22 implementers]
crates/plotlars-core/src/plot.rs
PlottersExt (Interface)
Plotters rendering extension trait. Provides static image output methods. Available on all types implementing the core [1 …
crates/plotlars-plotters/src/ext.rs
PlotlyExt (Interface)
Plotly rendering extension trait. Provides all visualization methods. [1 implementers]
crates/plotlars-plotly/src/ext.rs

Core symbols most depended-on inside this repo

x
called by 190
crates/plotlars-core/src/components/text.rs
y
called by 167
crates/plotlars-core/src/components/text.rs
get_numeric_column
called by 115
crates/plotlars-core/src/data.rs
size
called by 109
crates/plotlars-core/src/components/text.rs
font
called by 67
crates/plotlars-core/src/components/text.rs
plot
called by 64
crates/plotlars-plotly/src/subplot_grid/mod.rs
finish
called by 62
crates/plotlars-core/src/io/csv.rs
get_unique_groups
called by 61
crates/plotlars-core/src/data.rs

Shape

Function 707
Method 321
Class 90
Enum 26
Interface 3

Languages

Rust100%

Modules by API surface

crates/plotlars-plotly/src/converters/components.rs78 symbols
crates/plotlars-plotly/src/converters/trace.rs51 symbols
crates/plotlars-plotly/src/subplot_grid/shared.rs46 symbols
crates/plotlars-plotly/src/ext.rs46 symbols
crates/plotlars-core/src/components/axis.rs35 symbols
crates/plotlars-core/src/components/text.rs32 symbols
crates/plotlars-core/src/components/colorbar.rs32 symbols
crates/plotlars-plotly/src/faceting/mod.rs30 symbols
crates/plotlars-plotters/src/ext.rs26 symbols
crates/plotlars-core/src/plots/scatterplot.rs26 symbols
crates/plotlars-core/src/ir/trace.rs26 symbols
crates/plotlars-core/src/components/facet.rs22 symbols

For agents

$ claude mcp add plotlars \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact