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 x_cumsum: Vec<(String, f64)> = Vec::new();
22 let mut new_y = Vec::with_capacity(y_col.len());
23 let mut ymin_vals = Vec::with_capacity(y_col.len());
24
25 for (x, y) in x_col.iter().zip(y_col.iter()) {
26 let x_key = x.to_group_key();
27 let y_val = y.as_f64().unwrap_or(0.0);
28
29 let base = x_cumsum
30 .iter()
31 .find(|(k, _)| k == &x_key)
32 .map(|(_, v)| *v)
33 .unwrap_or(0.0);
34
35 ymin_vals.push(Value::Float(base));
36 new_y.push(Value::Float(base + y_val));
37
38 if let Some(entry) = x_cumsum.iter_mut().find(|(k, _)| k == &x_key) {
39 entry.1 += y_val;
40 } else {
41 x_cumsum.push((x_key, y_val));
42 }
43 }
44
45 if let Some(col) = data.column_mut("y") {
46 *col = new_y;
47 }
48 if !data.has_column("ymin") {
49 data.add_column("ymin".to_string(), ymin_vals);
50 } else if let Some(col) = data.column_mut("ymin") {
51 *col = ymin_vals;
52 }
53 }
54
55 fn name(&self) -> &str {
56 "stack"
57 }
58}