1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
use *;
use crate NodeArguments;
use ;
use crate Evaluable;
use ;
use proto;
use crate get_num_columns;
use ;
use ;
/// Maps data to bins.
///
/// Bins will be of the form [lower, upper) or (lower, upper].
///
/// # Arguments
/// * `data` - Data to be binned.
/// * `edges` - Values representing the edges of bins.
/// * `inclusive_left` - Whether or not the left edge of the bin is inclusive, i.e. the bins are of the form [lower, upper).
/// * `null` - Value to which to map if there is no valid bin (e.g. if the element falls outside the bin range).
/// * `side` - How to refer to each bin. Will be either the `left` edge, the `right` edge, or the `center` (the arithmetic mean of the two).
///
/// # Return
/// Binned data.
///
/// # Example
/// ```
/// use ndarray::{ArrayD, arr2, arr1};
/// use smartnoise_runtime::components::bin::{bin, BinSide};
///
/// let data = arr1(&[1.1, 2., 2.9, 4.1, 6.4]).into_dyn();
/// let edges = vec![vec![0., 1., 2., 3., 4., 5.]];
/// let inclusive_left = arr1(&[true]).into_dyn();
/// let null = arr1(&[-1.]).into_dyn();
/// let side = BinSide::Midpoint;
///
/// let binned = bin(&data, edges, &inclusive_left, &null, &side).unwrap();
/// assert!(binned == arr1(&[1.5, 2.5, 2.5, 4.5, -1.]).into_dyn());
/// ```
//pub fn bin<T>(data: &ArrayD<T>, edges: &ArrayD<T>, inclusive_left: &ArrayD<bool>)
// -> Result<ArrayD<String>> where T: Clone, T: PartialOrd, T: std::fmt::Display {
// /// Accepts vector of data and assigns each element to a bin
// /// NOTE: bin transformation has C-stability of 1
// ///
// /// # Arguments
// /// * `data` - Array of numeric data to be binned
// /// * `edges` - Array of bin edges, an array of n+1 edges will yield n bins
// /// * `inclusive_left` - Boolean for whether or not bins (representing numeric intervals) are closed on the left.
// /// If false, then bins are closed on the right.
// /// The leftmost and rightmost bins are automatically closed on the left/right (respectively),
// /// regardless of the value of `inclusive_left`.
// ///
// /// # Return
// /// ArrayD of bin assignments
// ///
// /// # Example
// /// ```
// /// // set up data
// /// use ndarray::{ArrayD, arr1, Array1};
// /// use smartnoise_runtime::utilities::transformations::bin;
// /// let data: ArrayD<f64> = arr1(&[1., 2., 3., 4., 5., 12., 19., 24., 90., 98.]).into_dyn();
// /// let edges: ArrayD<f64> = arr1(&[0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100.]).into_dyn();
// /// let inclusive_left: ArrayD<bool> = arr1(&[false]).into_dyn();
// ///
// /// // bin data
// /// let binned_data: ArrayD<String> = bin(&data, &edges, &inclusive_left)?;
// /// println!("{:?}", binned_data);
// /// ```
//
//
// // initialize new data -- this is what we ultimately return from the function
// let original_dim: u8 = data.ndim() as u8;
// let new_data: ArrayD<T> = convert_to_matrix(data);
// let mut new_bin_array: ArrayD<String> = Array::default(new_data.shape());
//
// let n_cols: i64 = data.len_of(Axis(0)) as i64;
//
// for k in 0..n_cols {
// // create vector versions of data and edges
// let data_vec: Vec<T> = data.slice(s![k as usize, ..]).clone().into_dimensionality::<Ix1>()?.to_vec();
// let mut sorted_edges: Vec<T> = edges.slice(s![k as usize, ..]).clone().into_dimensionality::<Ix1>()?.to_vec();
//
// // ensure edges are sorted in ascending order
// sorted_edges.sort_by(|a, b| a.partial_cmp(b).unwrap());
//
// // initialize output vector
// let mut bin_vec: Vec<String> = Vec::with_capacity(data_vec.len());
//
// // for each data element, look for correct bin and append name to bin_vec
// for i in 0..data_vec.len() {
// // append empty string if data are outside of bin ranges
// if data_vec[i] < sorted_edges[0] || data_vec[i] > sorted_edges[sorted_edges.len()-1] {
// bin_vec.push("".to_string());
// } else {
// // for each bin
// for j in 0..(sorted_edges.len()-1) {
// if // element is less than the right bin edge
// data_vec[i] < sorted_edges[j+1] ||
// // element is equal to the right bin edge and we are building our histogram to be 'right-edge inclusive'
// (data_vec[i] == sorted_edges[j+1] && inclusive_left[k as usize] == false) ||
// // element is equal to the right bin edge and we are checking our rightmost bin
// (data_vec[i] == sorted_edges[j+1] && j == (sorted_edges.len()-2)) {
// if j == 0 && inclusive_left[k as usize] == false {
// // leftmost bin must be left inclusive even if overall strategy is to be right inclusive
// bin_vec.push(format!("[{}, {}]", sorted_edges[j], sorted_edges[j+1]));
// } else if j == (sorted_edges.len()-2) && inclusive_left[k as usize] == true {
// // rightmost bin must be right inclusive even if overall strategy is to be left inclusive
// bin_vec.push(format!("[{}, {}]", sorted_edges[j], sorted_edges[j+1]));
// } else if inclusive_left[k as usize] == true {
// bin_vec.push(format!("[{}, {})", sorted_edges[j], sorted_edges[j+1]));
// } else {
// bin_vec.push(format!("({}, {}]", sorted_edges[j], sorted_edges[j+1]));
// }
// break;
// }
// }
// }
// }
// // convert bin vector to Array and return
// let bin_array: ArrayD<String> = arr1(&bin_vec).into_dyn();
// new_bin_array.slice_mut(s![k as usize, ..]).assign(&bin_array);
// }
// return Ok(convert_from_matrix(&new_bin_array, &original_dim));
//}
//
//
//
//
///// Accepts bin edges and bin definition rule and returns an array of bin names
/////
///// # Arguments
///// * `edges` - Array of bin edges, an array of n+1 edges will yield n bins
///// * `inclusive_left` - Boolean for whether or not bins (representing numeric intervals) are closed on the left.
///// If false, then bins are closed on the right.
///// The leftmost and rightmost bins are automatically closed on the left/right (respectively),
///// regardless of the value of `inclusive_left`.
/////
///// # Return
///// Array of bin names.
/////
///// Example
///// ```
///// use smartnoise_runtime::utilities::aggregations::get_bin_names;
///// use ndarray::prelude::*;
///// let edges: ArrayD<f64> = arr1(&[0., 10., 20.]).into_dyn();
/////
///// let inclusive_left: bool = true;
///// let bin_names: ArrayD<String> = get_bin_names(&edges, &inclusive_left);
///// assert_eq!(arr1(&["[0, 10)", "[10, 20]"]).into_dyn(), bin_names);
/////
///// let inclusive_left: bool = false;
///// let bin_names: ArrayD<String> = get_bin_names(&edges, &inclusive_left);
///// assert_eq!(arr1(&["[0, 10]", "(10, 20]"]).into_dyn(), bin_names);
///// ```
//pub fn get_bin_names(edges: &ArrayD<f64>, inclusive_left: &bool) -> ArrayD<String> {
//
// let mut bin_name_vec: Vec<String> = Vec::with_capacity(edges.len()-1);
// let mut left_edge = String::new();
// let mut right_edge = String::new();
// let mut bin_name = String::new();
// for i in 0..(edges.len()-1) {
// left_edge = edges[i].to_string();
// right_edge = edges[i+1].to_string();
// if i == 0 && inclusive_left == &false {
// bin_name = format!("[{}, {}]", left_edge, right_edge);
// } else if i == (edges.len()-2) && inclusive_left == &true {
// bin_name = format!("[{}, {}]", left_edge, right_edge);
// } else if inclusive_left == &true {
// bin_name = format!("[{}, {})", left_edge, right_edge);
// } else {
// bin_name = format!("({}, {}]", left_edge, right_edge);
// }
// bin_name_vec.push(bin_name);
// }
// return arr1(&bin_name_vec).into_dyn();
//}