ggplot_rs/position/
stack.rs1use crate::data::{DataFrame, Value};
2
3use super::{Position, PositionParams};
4
5pub struct PositionStack;
7
8impl Position for PositionStack {
9 fn compute(&self, data: &mut DataFrame, _params: &PositionParams) {
10 let x_col = match data.column("x") {
12 Some(c) => c.to_vec(),
13 None => return,
14 };
15 let y_col = match data.column("y") {
16 Some(c) => c.to_vec(),
17 None => return,
18 };
19
20 let mut totals: Vec<(String, f64)> = Vec::new();
24 for (x, y) in x_col.iter().zip(y_col.iter()) {
25 let x_key = x.to_group_key();
26 let y_val = y.as_f64().unwrap_or(0.0);
27 if let Some(entry) = totals.iter_mut().find(|(k, _)| k == &x_key) {
28 entry.1 += y_val;
29 } else {
30 totals.push((x_key, y_val));
31 }
32 }
33
34 let mut consumed: Vec<(String, f64)> = Vec::new();
35 let mut new_y = Vec::with_capacity(y_col.len());
36 let mut ymin_vals = Vec::with_capacity(y_col.len());
37
38 for (x, y) in x_col.iter().zip(y_col.iter()) {
39 let x_key = x.to_group_key();
40 let y_val = y.as_f64().unwrap_or(0.0);
41 let total = totals
42 .iter()
43 .find(|(k, _)| k == &x_key)
44 .map(|(_, v)| *v)
45 .unwrap_or(0.0);
46 let run = consumed
47 .iter()
48 .find(|(k, _)| k == &x_key)
49 .map(|(_, v)| *v)
50 .unwrap_or(0.0);
51
52 new_y.push(Value::Float(total - run));
54 ymin_vals.push(Value::Float(total - run - y_val));
55
56 if let Some(entry) = consumed.iter_mut().find(|(k, _)| k == &x_key) {
57 entry.1 += y_val;
58 } else {
59 consumed.push((x_key, y_val));
60 }
61 }
62
63 if let Some(col) = data.column_mut("y") {
64 *col = new_y;
65 }
66 if !data.has_column("ymin") {
67 data.add_column("ymin".to_string(), ymin_vals);
68 } else if let Some(col) = data.column_mut("ymin") {
69 *col = ymin_vals;
70 }
71 }
72
73 fn name(&self) -> &str {
74 "stack"
75 }
76}