dimensions/
dimensions.rs

1use plotlars::{
2    Axis, BarPlot, BoxPlot, Dimensions, Legend, Line, Orientation, Plot, Rgb, ScatterPlot, Shape,
3    SubplotGrid, Text, TickDirection, TimeSeriesPlot,
4};
5use polars::prelude::*;
6
7fn main() {
8    let penguins_dataset = LazyCsvReader::new(PlPath::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(PlPath::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(PlPath::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}