Skip to main content

SubplotGrid

Struct SubplotGrid 

Source
pub struct SubplotGrid { /* private fields */ }
Expand description

A structure representing a subplot grid layout.

The SubplotGrid struct facilitates the creation of multi-plot layouts arranged in a grid configuration. Plots are automatically arranged in rows and columns in row-major order (left-to-right, top-to-bottom). Each subplot retains its own title, axis labels, and legend, providing flexibility for displaying multiple related visualizations in a single figure.

§Features

  • Automatic grid layout with configurable rows and columns
  • Individual subplot titles (extracted from plot titles)
  • Independent axis labels for each subplot
  • Configurable horizontal and vertical spacing
  • Overall figure title
  • Sparse grid support (fewer plots than grid capacity)

Implementations§

Source§

impl SubplotGrid

Source

pub fn regular<'f1, 'f2>() -> SubplotGridRegularBuilder<'f1, 'f2>

Creates a subplot grid layout.

Arranges plots in a row × column grid with automatic positioning. Plots are placed in row-major order (left-to-right, top-to-bottom). Each subplot retains its individual title (from the plot’s plot_title), axis labels, and legend.

§Arguments
  • plots - Vector of plot references to arrange in the grid. Plots are positioned in row-major order.
  • rows - Number of rows in the grid (default: 1).
  • cols - Number of columns in the grid (default: 1).
  • title - Overall title for the entire subplot figure (optional).
  • h_gap - Horizontal spacing between columns (range: 0.0 to 1.0, default: 0.1).
  • v_gap - Vertical spacing between rows (range: 0.0 to 1.0, default: 0.1).
§Example
use plotlars::{
    Axis, BarPlot, BoxPlot, Legend, Line, Orientation, Plot, Rgb, ScatterPlot, Shape,
    SubplotGrid, Text, TickDirection, TimeSeriesPlot,
};
use polars::prelude::*;

let dataset1 = LazyCsvReader::new(PlRefPath::new("data/animal_statistics.csv"))
    .finish()
    .unwrap()
    .collect()
    .unwrap();

let plot1 = BarPlot::builder()
    .data(&dataset1)
    .labels("animal")
    .values("value")
    .orientation(Orientation::Vertical)
    .group("gender")
    .sort_groups_by(|a, b| a.len().cmp(&b.len()))
    .error("error")
    .colors(vec![Rgb(255, 127, 80), Rgb(64, 224, 208)])
    .plot_title(Text::from("Bar Plot").x(-0.05).y(1.35).size(14))
    .y_title(Text::from("value").x(-0.055).y(0.76))
    .x_title(Text::from("animal").x(0.97).y(-0.2))
    .legend(
        &Legend::new()
            .orientation(Orientation::Horizontal)
            .x(0.4)
            .y(1.2),
    )
    .build();

let dataset2 = LazyCsvReader::new(PlRefPath::new("data/penguins.csv"))
    .finish()
    .unwrap()
    .select([
        col("species"),
        col("sex").alias("gender"),
        col("flipper_length_mm").cast(DataType::Int16),
        col("body_mass_g").cast(DataType::Int16),
    ])
    .collect()
    .unwrap();

let axis = Axis::new()
    .show_line(true)
    .tick_direction(TickDirection::OutSide)
    .value_thousands(true);

let plot2 = ScatterPlot::builder()
    .data(&dataset2)
    .x("body_mass_g")
    .y("flipper_length_mm")
    .group("species")
    .sort_groups_by(|a, b| {
        if a.len() == b.len() {
            a.cmp(b)
        } else {
            a.len().cmp(&b.len())
        }
    })
    .opacity(0.5)
    .size(12)
    .colors(vec![Rgb(178, 34, 34), Rgb(65, 105, 225), Rgb(255, 140, 0)])
    .shapes(vec![Shape::Circle, Shape::Square, Shape::Diamond])
    .plot_title(Text::from("Scatter Plot").x(-0.075).y(1.35).size(14))
    .x_title(Text::from("body mass (g)").y(-0.4))
    .y_title(Text::from("flipper length (mm)").x(-0.078).y(0.5))
    .legend_title("species")
    .x_axis(&axis.clone().value_range(vec![2500.0, 6500.0]))
    .y_axis(&axis.clone().value_range(vec![170.0, 240.0]))
    .legend(&Legend::new().x(0.98).y(0.95))
    .build();

let dataset3 = LazyCsvReader::new(PlRefPath::new("data/debilt_2023_temps.csv"))
    .with_has_header(true)
    .with_try_parse_dates(true)
    .finish()
    .unwrap()
    .with_columns(vec![
        (col("tavg") / lit(10)).alias("avg"),
        (col("tmin") / lit(10)).alias("min"),
        (col("tmax") / lit(10)).alias("max"),
    ])
    .collect()
    .unwrap();

let plot3 = TimeSeriesPlot::builder()
    .data(&dataset3)
    .x("date")
    .y("avg")
    .additional_series(vec!["min", "max"])
    .colors(vec![Rgb(128, 128, 128), Rgb(0, 122, 255), Rgb(255, 128, 0)])
    .lines(vec![Line::Solid, Line::Dot, Line::Dot])
    .plot_title(Text::from("Time Series Plot").x(-0.05).y(1.35).size(14))
    .y_title(Text::from("temperature (ºC)").x(-0.055).y(0.6))
    .legend(&Legend::new().x(0.9).y(1.25))
    .build();

let plot4 = BoxPlot::builder()
    .data(&dataset2)
    .labels("species")
    .values("body_mass_g")
    .orientation(Orientation::Vertical)
    .group("gender")
    .box_points(true)
    .point_offset(-1.5)
    .jitter(0.01)
    .opacity(0.1)
    .colors(vec![Rgb(0, 191, 255), Rgb(57, 255, 20), Rgb(255, 105, 180)])
    .plot_title(Text::from("Box Plot").x(-0.075).y(1.35).size(14))
    .x_title(Text::from("species").y(-0.3))
    .y_title(Text::from("body mass (g)").x(-0.08).y(0.5))
    .legend_title(Text::from("gender").size(12))
    .y_axis(&Axis::new().value_thousands(true))
    .legend(&Legend::new().x(1.0))
    .build();

SubplotGrid::regular()
    .plots(vec![&plot1, &plot2, &plot3, &plot4])
    .rows(2)
    .cols(2)
    .v_gap(0.4)
    .title(
        Text::from("Regular Subplot Grid")
            .size(16)
            .font("Arial bold")
            .y(0.95),
    )
    .build()
    .plot();

Example

Examples found in repository?
examples/subplot_grid.rs (line 128)
15fn regular_grid_example() {
16    let dataset1 = LazyCsvReader::new(PlRefPath::new("data/animal_statistics.csv"))
17        .finish()
18        .unwrap()
19        .collect()
20        .unwrap();
21
22    let plot1 = BarPlot::builder()
23        .data(&dataset1)
24        .labels("animal")
25        .values("value")
26        .orientation(Orientation::Vertical)
27        .group("gender")
28        .sort_groups_by(|a, b| a.len().cmp(&b.len()))
29        .error("error")
30        .colors(vec![Rgb(255, 127, 80), Rgb(64, 224, 208)])
31        .plot_title(Text::from("Bar Plot").x(-0.05).y(1.35).size(14))
32        .y_title(Text::from("value").x(-0.055).y(0.76))
33        .x_title(Text::from("animal").x(0.97).y(-0.2))
34        .legend(
35            &Legend::new()
36                .orientation(Orientation::Horizontal)
37                .x(0.4)
38                .y(1.2),
39        )
40        .build();
41
42    let dataset2 = LazyCsvReader::new(PlRefPath::new("data/penguins.csv"))
43        .finish()
44        .unwrap()
45        .select([
46            col("species"),
47            col("sex").alias("gender"),
48            col("flipper_length_mm").cast(DataType::Int16),
49            col("body_mass_g").cast(DataType::Int16),
50        ])
51        .collect()
52        .unwrap();
53
54    let axis = Axis::new()
55        .show_line(true)
56        .tick_direction(TickDirection::OutSide)
57        .value_thousands(true);
58
59    let plot2 = ScatterPlot::builder()
60        .data(&dataset2)
61        .x("body_mass_g")
62        .y("flipper_length_mm")
63        .group("species")
64        .sort_groups_by(|a, b| {
65            if a.len() == b.len() {
66                a.cmp(b)
67            } else {
68                a.len().cmp(&b.len())
69            }
70        })
71        .opacity(0.5)
72        .size(12)
73        .colors(vec![Rgb(178, 34, 34), Rgb(65, 105, 225), Rgb(255, 140, 0)])
74        .shapes(vec![Shape::Circle, Shape::Square, Shape::Diamond])
75        .plot_title(Text::from("Scatter Plot").x(-0.075).y(1.35).size(14))
76        .x_title(Text::from("body mass (g)").y(-0.4))
77        .y_title(Text::from("flipper length (mm)").x(-0.078).y(0.5))
78        .legend_title("species")
79        .x_axis(&axis.clone().value_range(vec![2500.0, 6500.0]))
80        .y_axis(&axis.clone().value_range(vec![170.0, 240.0]))
81        .legend(&Legend::new().x(0.98).y(0.95))
82        .build();
83
84    let dataset3 = LazyCsvReader::new(PlRefPath::new("data/debilt_2023_temps.csv"))
85        .with_has_header(true)
86        .with_try_parse_dates(true)
87        .finish()
88        .unwrap()
89        .with_columns(vec![
90            (col("tavg") / lit(10)).alias("avg"),
91            (col("tmin") / lit(10)).alias("min"),
92            (col("tmax") / lit(10)).alias("max"),
93        ])
94        .collect()
95        .unwrap();
96
97    let plot3 = TimeSeriesPlot::builder()
98        .data(&dataset3)
99        .x("date")
100        .y("avg")
101        .additional_series(vec!["min", "max"])
102        .colors(vec![Rgb(128, 128, 128), Rgb(0, 122, 255), Rgb(255, 128, 0)])
103        .lines(vec![Line::Solid, Line::Dot, Line::Dot])
104        .plot_title(Text::from("Time Series Plot").x(-0.05).y(1.35).size(14))
105        .y_title(Text::from("temperature (ºC)").x(-0.055).y(0.6))
106        .legend(&Legend::new().x(0.9).y(1.25))
107        .build();
108
109    let plot4 = BoxPlot::builder()
110        .data(&dataset2)
111        .labels("species")
112        .values("body_mass_g")
113        .orientation(Orientation::Vertical)
114        .group("gender")
115        .box_points(true)
116        .point_offset(-1.5)
117        .jitter(0.01)
118        .opacity(0.1)
119        .colors(vec![Rgb(0, 191, 255), Rgb(57, 255, 20), Rgb(255, 105, 180)])
120        .plot_title(Text::from("Box Plot").x(-0.075).y(1.35).size(14))
121        .x_title(Text::from("species").y(-0.3))
122        .y_title(Text::from("body mass (g)").x(-0.08).y(0.5))
123        .legend_title(Text::from("gender").size(12))
124        .y_axis(&Axis::new().value_thousands(true))
125        .legend(&Legend::new().x(1.0))
126        .build();
127
128    SubplotGrid::regular()
129        .plots(vec![&plot1, &plot2, &plot3, &plot4])
130        .rows(2)
131        .cols(2)
132        .v_gap(0.4)
133        .title(
134            Text::from("Regular Subplot Grid")
135                .size(16)
136                .font("Arial bold")
137                .y(0.95),
138        )
139        .build()
140        .plot();
141}
142
143fn irregular_grid_example() {
144    let dataset1 = LazyCsvReader::new(PlRefPath::new("data/penguins.csv"))
145        .finish()
146        .unwrap()
147        .select([
148            col("species"),
149            col("sex").alias("gender"),
150            col("flipper_length_mm").cast(DataType::Int16),
151            col("body_mass_g").cast(DataType::Int16),
152        ])
153        .collect()
154        .unwrap();
155
156    let axis = Axis::new()
157        .show_line(true)
158        .show_grid(true)
159        .value_thousands(true)
160        .tick_direction(TickDirection::OutSide);
161
162    let plot1 = Histogram::builder()
163        .data(&dataset1)
164        .x("body_mass_g")
165        .group("species")
166        .opacity(0.5)
167        .colors(vec![Rgb(255, 165, 0), Rgb(147, 112, 219), Rgb(46, 139, 87)])
168        .plot_title(Text::from("Histogram").x(0.0).y(1.35).size(14))
169        .x_title(Text::from("body mass (g)").x(0.94).y(-0.35))
170        .y_title(Text::from("count").x(-0.062).y(0.83))
171        .x_axis(&axis)
172        .y_axis(&axis)
173        .legend_title(Text::from("species"))
174        .legend(&Legend::new().x(0.87).y(1.2))
175        .build();
176
177    let dataset2 = LazyCsvReader::new(PlRefPath::new("data/stock_prices.csv"))
178        .finish()
179        .unwrap()
180        .collect()
181        .unwrap();
182
183    let increasing = Direction::new()
184        .line_color(Rgb(0, 200, 100))
185        .line_width(0.5);
186
187    let decreasing = Direction::new()
188        .line_color(Rgb(200, 50, 50))
189        .line_width(0.5);
190
191    let plot2 = CandlestickPlot::builder()
192        .data(&dataset2)
193        .dates("date")
194        .open("open")
195        .high("high")
196        .low("low")
197        .close("close")
198        .increasing(&increasing)
199        .decreasing(&decreasing)
200        .whisker_width(0.1)
201        .plot_title(Text::from("Candlestick").x(0.0).y(1.35).size(14))
202        .y_title(Text::from("price ($)").x(-0.06).y(0.76))
203        .y_axis(&Axis::new().show_axis(true).show_grid(true))
204        .build();
205
206    let dataset3 = LazyCsvReader::new(PlRefPath::new("data/heatmap.csv"))
207        .finish()
208        .unwrap()
209        .collect()
210        .unwrap();
211
212    let plot3 = HeatMap::builder()
213        .data(&dataset3)
214        .x("x")
215        .y("y")
216        .z("z")
217        .color_bar(
218            &ColorBar::new()
219                .value_exponent(ValueExponent::None)
220                .separate_thousands(true)
221                .tick_length(5)
222                .tick_step(5000.0),
223        )
224        .plot_title(Text::from("Heat Map").x(0.0).y(1.35).size(14))
225        .color_scale(Palette::Viridis)
226        .build();
227
228    SubplotGrid::irregular()
229        .plots(vec![
230            (&plot1, 0, 0, 1, 1),
231            (&plot2, 0, 1, 1, 1),
232            (&plot3, 1, 0, 1, 2),
233        ])
234        .rows(2)
235        .cols(2)
236        .v_gap(0.35)
237        .h_gap(0.05)
238        .title(
239            Text::from("Irregular Subplot Grid")
240                .size(16)
241                .font("Arial bold")
242                .y(0.95),
243        )
244        .build()
245        .plot();
246}
247
248fn mixed_grid_example() {
249    // 2D cartesian scatter (baseline)
250    let penguins = LazyCsvReader::new(PlRefPath::new("data/penguins.csv"))
251        .finish()
252        .unwrap()
253        .collect()
254        .unwrap()
255        .lazy()
256        .select([
257            col("species"),
258            col("bill_length_mm"),
259            col("flipper_length_mm"),
260            col("body_mass_g"),
261        ])
262        .collect()
263        .unwrap();
264
265    let scatter_2d = ScatterPlot::builder()
266        .data(&penguins)
267        .x("bill_length_mm")
268        .y("flipper_length_mm")
269        .group("species")
270        .opacity(0.65)
271        .size(10)
272        .plot_title(Text::from("Penguins 2D").y(1.3))
273        .build();
274
275    // 3D scene subplot
276    let scatter_3d = Scatter3dPlot::builder()
277        .data(&penguins)
278        .x("bill_length_mm")
279        .y("flipper_length_mm")
280        .z("body_mass_g")
281        .group("species")
282        .opacity(0.35)
283        .size(6)
284        .plot_title(Text::from("Penguins 3D").y(1.45))
285        .build();
286
287    // Polar subplot
288    let polar_df = LazyCsvReader::new(PlRefPath::new("data/product_comparison_polar.csv"))
289        .finish()
290        .unwrap()
291        .collect()
292        .unwrap();
293
294    let polar = ScatterPolar::builder()
295        .data(&polar_df)
296        .theta("angle")
297        .r("score")
298        .group("product")
299        .mode(Mode::LinesMarkers)
300        .size(10)
301        .plot_title(Text::from("Product Comparison (Polar)").y(1.5).x(0.72))
302        .legend(&Legend::new().x(0.8))
303        .build();
304
305    // Domain-based subplot (Sankey)
306    let sankey_df = LazyCsvReader::new(PlRefPath::new("data/energy_transition.csv"))
307        .finish()
308        .unwrap()
309        .collect()
310        .unwrap();
311
312    let sankey = SankeyDiagram::builder()
313        .data(&sankey_df)
314        .sources("source")
315        .targets("target")
316        .values("value")
317        .orientation(Orientation::Horizontal)
318        .arrangement(Arrangement::Freeform)
319        .plot_title(Text::from("Energy Flow").y(1.2))
320        .build();
321
322    // Mapbox subplot
323    let map_df = LazyCsvReader::new(PlRefPath::new("data/cities.csv"))
324        .finish()
325        .unwrap()
326        .collect()
327        .unwrap();
328
329    let scatter_map = ScatterMap::builder()
330        .data(&map_df)
331        .latitude("latitude")
332        .longitude("longitude")
333        .group("city")
334        .zoom(4)
335        .center([50.0, 5.0])
336        .opacity(0.8)
337        .plot_title(Text::from("Cities (Mapbox)").y(1.2))
338        .build();
339
340    // Geo subplot
341    let geo_df = LazyCsvReader::new(PlRefPath::new("data/world_cities.csv"))
342        .finish()
343        .unwrap()
344        .collect()
345        .unwrap();
346
347    let scatter_geo = ScatterGeo::builder()
348        .data(&geo_df)
349        .lat("lat")
350        .lon("lon")
351        .group("continent")
352        .mode(Mode::Markers)
353        .size(10)
354        .color(Rgb(255, 140, 0))
355        .shape(Shape::Circle)
356        .plot_title(Text::from("Global Cities (Geo)").x(0.65).y(1.2))
357        .legend(&Legend::new().x(0.8))
358        .build();
359
360    SubplotGrid::regular()
361        .plots(vec![
362            &scatter_2d,
363            &scatter_3d,
364            &polar,
365            &sankey,
366            &scatter_map,
367            &scatter_geo,
368        ])
369        .rows(2)
370        .cols(3)
371        .h_gap(0.12)
372        .v_gap(0.22)
373        .title(
374            Text::from("Mixed Subplot Grid")
375                .size(16)
376                .font("Arial bold")
377                .y(0.95),
378        )
379        .build()
380        .plot();
381}
More examples
Hide additional examples
examples/dimensions.rs (line 132)
7fn main() {
8    let penguins_dataset = LazyCsvReader::new(PlRefPath::new("data/penguins.csv"))
9        .finish()
10        .unwrap()
11        .select([
12            col("species"),
13            col("sex").alias("gender"),
14            col("flipper_length_mm").cast(DataType::Int16),
15            col("body_mass_g").cast(DataType::Int16),
16        ])
17        .collect()
18        .unwrap();
19
20    let temperature_dataset = LazyCsvReader::new(PlRefPath::new("data/debilt_2023_temps.csv"))
21        .with_has_header(true)
22        .with_try_parse_dates(true)
23        .finish()
24        .unwrap()
25        .with_columns(vec![
26            (col("tavg") / lit(10)).alias("tavg"),
27            (col("tmin") / lit(10)).alias("tmin"),
28            (col("tmax") / lit(10)).alias("tmax"),
29        ])
30        .collect()
31        .unwrap();
32
33    let animals_dataset = LazyCsvReader::new(PlRefPath::new("data/animal_statistics.csv"))
34        .finish()
35        .unwrap()
36        .collect()
37        .unwrap();
38
39    let axis = Axis::new()
40        .show_line(true)
41        .tick_direction(TickDirection::OutSide)
42        .value_thousands(true);
43
44    let plot1 = TimeSeriesPlot::builder()
45        .data(&temperature_dataset)
46        .x("date")
47        .y("tavg")
48        .additional_series(vec!["tmin", "tmax"])
49        .colors(vec![Rgb(128, 128, 128), Rgb(0, 122, 255), Rgb(255, 128, 0)])
50        .lines(vec![Line::Solid, Line::Dot, Line::Dot])
51        .plot_title(
52            Text::from("De Bilt Temperature 2023")
53                .font("Arial Bold")
54                .size(16),
55        )
56        .y_title(Text::from("temperature (°C)").size(13).x(-0.08))
57        // .legend_title(Text::from("Measure").size(12))
58        .legend(&Legend::new().x(0.1).y(0.9))
59        .build();
60
61    let plot2 = ScatterPlot::builder()
62        .data(&penguins_dataset)
63        .x("body_mass_g")
64        .y("flipper_length_mm")
65        .group("species")
66        .sort_groups_by(|a, b| {
67            if a.len() == b.len() {
68                a.cmp(b)
69            } else {
70                a.len().cmp(&b.len())
71            }
72        })
73        .opacity(0.6)
74        .size(10)
75        .colors(vec![Rgb(178, 34, 34), Rgb(65, 105, 225), Rgb(255, 140, 0)])
76        .shapes(vec![Shape::Circle, Shape::Square, Shape::Diamond])
77        .plot_title(Text::from("Penguin Morphology").font("Arial Bold").size(16))
78        .x_title(Text::from("body mass (g)").size(13))
79        .y_title(Text::from("flipper length (mm)").size(13).x(-0.11))
80        .legend_title(Text::from("Species").size(12))
81        .x_axis(&axis.clone().value_range(vec![2500.0, 6500.0]))
82        .y_axis(&axis.clone().value_range(vec![170.0, 240.0]))
83        .legend(&Legend::new().x(0.85).y(0.4))
84        .build();
85
86    let plot3 = BarPlot::builder()
87        .data(&animals_dataset)
88        .labels("animal")
89        .values("value")
90        .orientation(Orientation::Vertical)
91        .group("gender")
92        .sort_groups_by(|a, b| a.len().cmp(&b.len()))
93        .error("error")
94        .colors(vec![Rgb(255, 127, 80), Rgb(64, 224, 208)])
95        .plot_title(Text::from("Animal Statistics").font("Arial Bold").size(16))
96        .x_title(Text::from("animal").size(13))
97        .y_title(Text::from("value").size(13))
98        .legend_title(Text::from("Gender").size(12))
99        .legend(
100            &Legend::new()
101                .orientation(Orientation::Horizontal)
102                .x(0.35)
103                .y(0.9),
104        )
105        .build();
106
107    let plot4 = BoxPlot::builder()
108        .data(&penguins_dataset)
109        .labels("species")
110        .values("body_mass_g")
111        .orientation(Orientation::Vertical)
112        .group("gender")
113        .box_points(true)
114        .point_offset(-1.5)
115        .jitter(0.01)
116        .opacity(0.15)
117        .colors(vec![Rgb(0, 191, 255), Rgb(57, 255, 20), Rgb(255, 105, 180)])
118        .plot_title(
119            Text::from("Body Mass Distribution")
120                .font("Arial Bold")
121                .size(16),
122        )
123        .x_title(Text::from("species").size(13))
124        .y_title(Text::from("body mass (g)").size(13).x(-0.12))
125        .legend_title(Text::from("Gender").size(12))
126        .y_axis(&Axis::new().value_thousands(true))
127        .legend(&Legend::new().x(0.85).y(0.9))
128        .build();
129
130    let dimensions = Dimensions::new().width(1400).height(850).auto_size(false);
131
132    SubplotGrid::regular()
133        .plots(vec![&plot1, &plot2, &plot3, &plot4])
134        .rows(2)
135        .cols(2)
136        .v_gap(0.3)
137        .h_gap(0.2)
138        .dimensions(&dimensions)
139        .title(
140            Text::from("Scientific Data Visualization Dashboard")
141                .size(26)
142                .font("Arial Bold"),
143        )
144        .build()
145        .plot();
146}
Source

pub fn irregular<'f1, 'f2>() -> SubplotGridIrregularBuilder<'f1, 'f2>

Creates an irregular grid subplot layout with custom row/column spanning.

Allows plots to span multiple rows and/or columns, enabling dashboard-style layouts and asymmetric grid arrangements. Each plot explicitly specifies its position and span.

§Arguments
  • plots - Vector of tuples (plot, row, col, rowspan, colspan) where:
    • plot: Reference to the plot
    • row: Starting row (0-indexed)
    • col: Starting column (0-indexed)
    • rowspan: Number of rows to span (minimum 1)
    • colspan: Number of columns to span (minimum 1)
  • rows - Total number of rows in the grid (default: 1).
  • cols - Total number of columns in the grid (default: 1).
  • title - Overall title for the subplot figure (optional).
  • h_gap - Horizontal spacing between columns (range: 0.0 to 1.0, default: 0.1).
  • v_gap - Vertical spacing between rows (range: 0.0 to 1.0, default: 0.1).
§Example
use plotlars::{
    Axis, CandlestickPlot, ColorBar, Direction, HeatMap, Histogram, Legend, Palette, Plot,
    Rgb, SubplotGrid, Text, TickDirection, ValueExponent,
};
use polars::prelude::*;

let dataset1 = LazyCsvReader::new(PlRefPath::new("data/penguins.csv"))
    .finish()
    .unwrap()
    .select([
        col("species"),
        col("sex").alias("gender"),
        col("flipper_length_mm").cast(DataType::Int16),
        col("body_mass_g").cast(DataType::Int16),
    ])
    .collect()
    .unwrap();

let axis = Axis::new()
    .show_line(true)
    .show_grid(true)
    .value_thousands(true)
    .tick_direction(TickDirection::OutSide);

let plot1 = Histogram::builder()
    .data(&dataset1)
    .x("body_mass_g")
    .group("species")
    .opacity(0.5)
    .colors(vec![Rgb(255, 165, 0), Rgb(147, 112, 219), Rgb(46, 139, 87)])
    .plot_title(Text::from("Histogram").x(0.0).y(1.35).size(14))
    .x_title(Text::from("body mass (g)").x(0.94).y(-0.35))
    .y_title(Text::from("count").x(-0.062).y(0.83))
    .x_axis(&axis)
    .y_axis(&axis)
    .legend_title(Text::from("species"))
    .legend(&Legend::new().x(0.87).y(1.2))
    .build();

let dataset2 = LazyCsvReader::new(PlRefPath::new("data/stock_prices.csv"))
    .finish()
    .unwrap()
    .collect()
    .unwrap();

let increasing = Direction::new()
    .line_color(Rgb(0, 200, 100))
    .line_width(0.5);

let decreasing = Direction::new()
    .line_color(Rgb(200, 50, 50))
    .line_width(0.5);

let plot2 = CandlestickPlot::builder()
    .data(&dataset2)
    .dates("date")
    .open("open")
    .high("high")
    .low("low")
    .close("close")
    .increasing(&increasing)
    .decreasing(&decreasing)
    .whisker_width(0.1)
    .plot_title(Text::from("Candlestick").x(0.0).y(1.35).size(14))
    .y_title(Text::from("Price ($)").x(-0.06).y(0.76))
    .y_axis(&Axis::new().show_axis(true).show_grid(true))
    .build();

let dataset3 = LazyCsvReader::new(PlRefPath::new("data/heatmap.csv"))
    .finish()
    .unwrap()
    .collect()
    .unwrap();

let plot3 = HeatMap::builder()
    .data(&dataset3)
    .x("x")
    .y("y")
    .z("z")
    .color_bar(
        &ColorBar::new()
            .value_exponent(ValueExponent::None)
            .separate_thousands(true)
            .tick_length(5)
            .tick_step(5000.0),
    )
    .plot_title(Text::from("Heat Map").x(0.0).y(1.35).size(14))
    .color_scale(Palette::Viridis)
    .build();

SubplotGrid::irregular()
    .plots(vec![
        (&plot1, 0, 0, 1, 1),
        (&plot2, 0, 1, 1, 1),
        (&plot3, 1, 0, 1, 2),
    ])
    .rows(2)
    .cols(2)
    .v_gap(0.35)
    .h_gap(0.05)
    .title(
        Text::from("Irregular Subplot Grid")
            .size(16)
            .font("Arial bold")
            .y(0.95),
    )
    .build()
    .plot();

Example

Examples found in repository?
examples/subplot_grid.rs (line 228)
143fn irregular_grid_example() {
144    let dataset1 = LazyCsvReader::new(PlRefPath::new("data/penguins.csv"))
145        .finish()
146        .unwrap()
147        .select([
148            col("species"),
149            col("sex").alias("gender"),
150            col("flipper_length_mm").cast(DataType::Int16),
151            col("body_mass_g").cast(DataType::Int16),
152        ])
153        .collect()
154        .unwrap();
155
156    let axis = Axis::new()
157        .show_line(true)
158        .show_grid(true)
159        .value_thousands(true)
160        .tick_direction(TickDirection::OutSide);
161
162    let plot1 = Histogram::builder()
163        .data(&dataset1)
164        .x("body_mass_g")
165        .group("species")
166        .opacity(0.5)
167        .colors(vec![Rgb(255, 165, 0), Rgb(147, 112, 219), Rgb(46, 139, 87)])
168        .plot_title(Text::from("Histogram").x(0.0).y(1.35).size(14))
169        .x_title(Text::from("body mass (g)").x(0.94).y(-0.35))
170        .y_title(Text::from("count").x(-0.062).y(0.83))
171        .x_axis(&axis)
172        .y_axis(&axis)
173        .legend_title(Text::from("species"))
174        .legend(&Legend::new().x(0.87).y(1.2))
175        .build();
176
177    let dataset2 = LazyCsvReader::new(PlRefPath::new("data/stock_prices.csv"))
178        .finish()
179        .unwrap()
180        .collect()
181        .unwrap();
182
183    let increasing = Direction::new()
184        .line_color(Rgb(0, 200, 100))
185        .line_width(0.5);
186
187    let decreasing = Direction::new()
188        .line_color(Rgb(200, 50, 50))
189        .line_width(0.5);
190
191    let plot2 = CandlestickPlot::builder()
192        .data(&dataset2)
193        .dates("date")
194        .open("open")
195        .high("high")
196        .low("low")
197        .close("close")
198        .increasing(&increasing)
199        .decreasing(&decreasing)
200        .whisker_width(0.1)
201        .plot_title(Text::from("Candlestick").x(0.0).y(1.35).size(14))
202        .y_title(Text::from("price ($)").x(-0.06).y(0.76))
203        .y_axis(&Axis::new().show_axis(true).show_grid(true))
204        .build();
205
206    let dataset3 = LazyCsvReader::new(PlRefPath::new("data/heatmap.csv"))
207        .finish()
208        .unwrap()
209        .collect()
210        .unwrap();
211
212    let plot3 = HeatMap::builder()
213        .data(&dataset3)
214        .x("x")
215        .y("y")
216        .z("z")
217        .color_bar(
218            &ColorBar::new()
219                .value_exponent(ValueExponent::None)
220                .separate_thousands(true)
221                .tick_length(5)
222                .tick_step(5000.0),
223        )
224        .plot_title(Text::from("Heat Map").x(0.0).y(1.35).size(14))
225        .color_scale(Palette::Viridis)
226        .build();
227
228    SubplotGrid::irregular()
229        .plots(vec![
230            (&plot1, 0, 0, 1, 1),
231            (&plot2, 0, 1, 1, 1),
232            (&plot3, 1, 0, 1, 2),
233        ])
234        .rows(2)
235        .cols(2)
236        .v_gap(0.35)
237        .h_gap(0.05)
238        .title(
239            Text::from("Irregular Subplot Grid")
240                .size(16)
241                .font("Arial bold")
242                .y(0.95),
243        )
244        .build()
245        .plot();
246}

Trait Implementations§

Source§

impl Clone for SubplotGrid

Source§

fn clone(&self) -> SubplotGrid

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Serialize for SubplotGrid

Source§

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Key for T
where T: Clone,

Source§

fn align() -> usize

The alignment necessary for the key. Must return a power of two.
Source§

fn size(&self) -> usize

The size of the key in bytes.
Source§

unsafe fn init(&self, ptr: *mut u8)

Initialize the key in the given memory location. Read more
Source§

unsafe fn get<'a>(ptr: *const u8) -> &'a T

Get a reference to the key from the given memory location. Read more
Source§

unsafe fn drop_in_place(ptr: *mut u8)

Drop the key in place. Read more
Source§

impl<T> Plot for T
where T: PlotHelper + Serialize + Clone,

Source§

fn plot(&self)

Source§

fn write_html(&self, path: impl Into<String>)

Source§

fn to_json(&self) -> Result<String, Error>

Source§

fn to_html(&self) -> String

Source§

fn to_inline_html(&self, plot_div_id: Option<&str>) -> String

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> PlanCallbackArgs for T

Source§

impl<T> PlanCallbackOut for T