Skip to main content

plotly_dimensions/
plotly_dimensions.rs

1use plotlars::polars::prelude::*;
2use plotlars::{
3    Axis, BarPlot, BoxPlot, CsvReader, Dimensions, Legend, Line, Orientation, Rgb, ScatterPlot,
4    Shape, SubplotGrid, Text, TickDirection, TimeSeriesPlot,
5};
6
7fn main() {
8    let penguins_dataset = CsvReader::new("data/penguins.csv")
9        .finish()
10        .unwrap()
11        .lazy()
12        .select([
13            col("species"),
14            col("sex").alias("gender"),
15            col("flipper_length_mm").cast(DataType::Int16),
16            col("body_mass_g").cast(DataType::Int16),
17        ])
18        .collect()
19        .unwrap();
20
21    let temperature_dataset = CsvReader::new("data/debilt_2023_temps.csv")
22        .has_header(true)
23        .try_parse_dates(true)
24        .finish()
25        .unwrap()
26        .lazy()
27        .with_columns(vec![
28            (col("tavg") / lit(10)).alias("tavg"),
29            (col("tmin") / lit(10)).alias("tmin"),
30            (col("tmax") / lit(10)).alias("tmax"),
31        ])
32        .collect()
33        .unwrap();
34
35    let animals_dataset = CsvReader::new("data/animal_statistics.csv")
36        .finish()
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 Black")
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(
78            Text::from("Penguin Morphology")
79                .font("Arial Black")
80                .size(16),
81        )
82        .x_title(Text::from("body mass (g)").size(13))
83        .y_title(Text::from("flipper length (mm)").size(13).x(-0.11))
84        .legend_title(Text::from("Species").size(12))
85        .x_axis(&axis.clone().value_range(2500.0, 6500.0))
86        .y_axis(&axis.clone().value_range(170.0, 240.0))
87        .legend(&Legend::new().x(0.85).y(0.4))
88        .build();
89
90    let plot3 = BarPlot::builder()
91        .data(&animals_dataset)
92        .labels("animal")
93        .values("value")
94        .orientation(Orientation::Vertical)
95        .group("gender")
96        .sort_groups_by(|a, b| a.len().cmp(&b.len()))
97        .error("error")
98        .colors(vec![Rgb(255, 127, 80), Rgb(64, 224, 208)])
99        .plot_title(Text::from("Animal Statistics").font("Arial Black").size(16))
100        .x_title(Text::from("animal").size(13))
101        .y_title(Text::from("value").size(13))
102        .legend_title(Text::from("Gender").size(12))
103        .legend(
104            &Legend::new()
105                .orientation(Orientation::Horizontal)
106                .x(0.35)
107                .y(0.9),
108        )
109        .build();
110
111    let plot4 = BoxPlot::builder()
112        .data(&penguins_dataset)
113        .labels("species")
114        .values("body_mass_g")
115        .orientation(Orientation::Vertical)
116        .group("gender")
117        .box_points(true)
118        .point_offset(-1.5)
119        .jitter(0.01)
120        .opacity(0.15)
121        .colors(vec![Rgb(0, 191, 255), Rgb(57, 255, 20), Rgb(255, 105, 180)])
122        .plot_title(
123            Text::from("Body Mass Distribution")
124                .font("Arial Black")
125                .size(16),
126        )
127        .x_title(Text::from("species").size(13))
128        .y_title(Text::from("body mass (g)").size(13).x(-0.12))
129        .legend_title(Text::from("Gender").size(12))
130        .y_axis(&Axis::new().value_thousands(true))
131        .legend(&Legend::new().x(0.85).y(0.9))
132        .build();
133
134    let dimensions = Dimensions::new().width(1400).height(850).auto_size(false);
135
136    SubplotGrid::regular()
137        .plots(vec![&plot1, &plot2, &plot3, &plot4])
138        .rows(2)
139        .cols(2)
140        .v_gap(0.3)
141        .h_gap(0.2)
142        .dimensions(&dimensions)
143        .title(
144            Text::from("Scientific Data Visualization Dashboard")
145                .size(26)
146                .font("Arial Black"),
147        )
148        .build()
149        .plot();
150}