arr_rs/core/operations/joining.rs
1use crate::{
2 core::prelude::*,
3 errors::prelude::*,
4 extensions::prelude::*,
5 validators::prelude::*,
6};
7
8/// `ArrayTrait` - Array Joining functions
9pub trait ArrayJoining<T: ArrayElement> where Self: Sized + Clone {
10
11 /// Join a sequence of arrays along an existing axis
12 ///
13 /// # Arguments
14 ///
15 /// * `arrs` - arrays to concatenate
16 /// * `axis` - the axis along which to concat. optional, if None - arrays are flattened
17 ///
18 /// # Examples
19 /// ```
20 /// use arr_rs::prelude::*;
21 ///
22 /// let arr = array!(i32, [1, 2, 3]).unwrap();
23 /// let other = array!(i32, [4, 5, 6]).unwrap();
24 /// let expected = array!(i32, [1, 2, 3, 4, 5, 6]).unwrap();
25 /// assert_eq!(expected, Array::<i32>::concatenate(vec![arr, other], None).unwrap());
26 ///
27 /// let arr = array!(i32, [[1, 2], [3, 4]]).unwrap();
28 /// let other = array!(i32, [[5, 6]]).unwrap();
29 /// let expected = array!(i32, [[1, 2], [3, 4], [5, 6]]).unwrap();
30 /// assert_eq!(expected, Array::<i32>::concatenate(vec![arr, other], Some(0)).unwrap());
31 /// ```
32 ///
33 /// # Errors
34 ///
35 /// may returns `ArrayError`
36 fn concatenate(arrs: Vec<Array<T>>, axis: Option<usize>) -> Result<Array<T>, ArrayError>;
37
38 /// Join a sequence of arrays along a new axis
39 ///
40 /// # Arguments
41 ///
42 /// * `arrs` - arrays to stack
43 /// * `axis` - the axis along which to concat. optional, defaults to 0
44 ///
45 /// # Examples
46 /// ```
47 /// use arr_rs::prelude::*;
48 ///
49 /// let arr = array!(i32, [1, 2, 3]).unwrap();
50 /// let other = array!(i32, [4, 5, 6]).unwrap();
51 /// let expected = array!(i32, [[1, 2, 3], [4, 5, 6]]).unwrap();
52 /// assert_eq!(expected, Array::<i32>::stack(vec![arr, other], None).unwrap());
53 ///
54 /// let arr = array!(i32, [[1, 2], [3, 4]]).unwrap();
55 /// let other = array!(i32, [[5, 6], [7, 8]]).unwrap();
56 /// let expected = array!(i32, [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]).unwrap();
57 /// assert_eq!(expected, Array::<i32>::stack(vec![arr, other], Some(0)).unwrap());
58 /// ```
59 ///
60 /// # Errors
61 ///
62 /// may returns `ArrayError`
63 fn stack(arrs: Vec<Array<T>>, axis: Option<usize>) -> Result<Array<T>, ArrayError>;
64
65 /// Stack arrays in sequence vertically (row wise)
66 ///
67 /// # Arguments
68 ///
69 /// * `arrs` - arrays to stack
70 ///
71 /// # Examples
72 /// ```
73 /// use arr_rs::prelude::*;
74 ///
75 /// let arr = array!(i32, [1, 2, 3]).unwrap();
76 /// let other = array!(i32, [4, 5, 6]).unwrap();
77 /// let expected = array!(i32, [[1, 2, 3], [4, 5, 6]]).unwrap();
78 /// assert_eq!(expected, Array::<i32>::vstack(vec![arr, other]).unwrap());
79 ///
80 /// let arr = array!(i32, [[1], [2], [3]]).unwrap();
81 /// let other = array!(i32, [[4], [5], [6]]).unwrap();
82 /// let expected = array!(i32, [[1], [2], [3], [4], [5], [6]]).unwrap();
83 /// assert_eq!(expected, Array::<i32>::vstack(vec![arr, other]).unwrap());
84 /// ```
85 ///
86 /// # Errors
87 ///
88 /// may returns `ArrayError`
89 fn vstack(arrs: Vec<Array<T>>) -> Result<Array<T>, ArrayError>;
90
91 /// Stack arrays in sequence horizontally (column wise)
92 ///
93 /// # Arguments
94 ///
95 /// * `arrs` - arrays to stack
96 ///
97 /// # Examples
98 /// ```
99 /// use arr_rs::prelude::*;
100 ///
101 /// let arr = array!(i32, [1, 2, 3]).unwrap();
102 /// let other = array!(i32, [4, 5, 6]).unwrap();
103 /// let expected = array!(i32, [1, 2, 3, 4, 5, 6]).unwrap();
104 /// assert_eq!(expected, Array::<i32>::hstack(vec![arr, other]).unwrap());
105 ///
106 /// let arr = array!(i32, [[1], [2], [3]]).unwrap();
107 /// let other = array!(i32, [[4], [5], [6]]).unwrap();
108 /// let expected = array!(i32, [[1, 4], [2, 5], [3, 6]]).unwrap();
109 /// assert_eq!(expected, Array::<i32>::hstack(vec![arr, other]).unwrap());
110 /// ```
111 ///
112 /// # Errors
113 ///
114 /// may returns `ArrayError`
115 fn hstack(arrs: Vec<Array<T>>) -> Result<Array<T>, ArrayError>;
116
117 /// Stack arrays in sequence depth wise (along third axis)
118 ///
119 /// # Arguments
120 ///
121 /// * `arrs` - arrays to stack
122 ///
123 /// # Examples
124 /// ```
125 /// use arr_rs::prelude::*;
126 ///
127 /// let arr = array!(i32, [1, 2, 3]).unwrap();
128 /// let other = array!(i32, [4, 5, 6]).unwrap();
129 /// let expected = array!(i32, [[[1, 4], [2, 5], [3, 6]]]).unwrap();
130 /// assert_eq!(expected, Array::<i32>::dstack(vec![arr, other]).unwrap());
131 ///
132 /// let arr = array!(i32, [[1], [2], [3]]).unwrap();
133 /// let other = array!(i32, [[4], [5], [6]]).unwrap();
134 /// let expected = array!(i32, [[[1, 4]], [[2, 5]], [[3, 6]]]).unwrap();
135 /// assert_eq!(expected, Array::<i32>::dstack(vec![arr, other]).unwrap());
136 /// ```
137 ///
138 /// # Errors
139 ///
140 /// may returns `ArrayError`
141 fn dstack(arrs: Vec<Array<T>>) -> Result<Array<T>, ArrayError>;
142
143 /// Stack 1d or 2d arrays as columns into a 2d array
144 /// `row_stack` is an alias for vstack
145 ///
146 /// # Arguments
147 ///
148 /// * `arrs` - arrays to stack
149 ///
150 /// # Examples
151 /// ```
152 /// use arr_rs::prelude::*;
153 ///
154 /// let arr = array!(i32, [1, 2, 3]).unwrap();
155 /// let other = array!(i32, [4, 5, 6]).unwrap();
156 /// let expected = array!(i32, [[1, 4], [2, 5], [3, 6]]).unwrap();
157 /// assert_eq!(expected, Array::<i32>::column_stack(vec![arr, other]).unwrap());
158 /// ```
159 ///
160 /// # Errors
161 ///
162 /// may returns `ArrayError`
163 fn column_stack(arrs: Vec<Array<T>>) -> Result<Array<T>, ArrayError>;
164
165 /// Stack arrays in sequence vertically (row wise)
166 ///
167 /// # Arguments
168 ///
169 /// * `arrs` - arrays to stack
170 ///
171 /// # Examples
172 /// ```
173 /// use arr_rs::prelude::*;
174 ///
175 /// let arr = array!(i32, [1, 2, 3]).unwrap();
176 /// let other = array!(i32, [4, 5, 6]).unwrap();
177 /// let expected = array!(i32, [[1, 2, 3], [4, 5, 6]]).unwrap();
178 /// assert_eq!(expected, Array::<i32>::row_stack(vec![arr, other]).unwrap());
179 ///
180 /// let arr = array!(i32, [[1], [2], [3]]).unwrap();
181 /// let other = array!(i32, [[4], [5], [6]]).unwrap();
182 /// let expected = array!(i32, [[1], [2], [3], [4], [5], [6]]).unwrap();
183 /// assert_eq!(expected, Array::<i32>::row_stack(vec![arr, other]).unwrap());
184 /// ```
185 ///
186 /// # Errors
187 ///
188 /// may returns `ArrayError`
189 fn row_stack(arrs: Vec<Array<T>>) -> Result<Array<T>, ArrayError>;
190}
191
192impl <T: ArrayElement> ArrayJoining<T> for Array<T> {
193
194 fn concatenate(arrs: Vec<Self>, axis: Option<usize>) -> Result<Self, ArrayError> {
195 if arrs.is_empty() { Self::empty() }
196 else {
197 if let Some(axis) = axis { arrs.validate_stack_shapes(axis, axis)?; }
198
199 let (mut arrs, initial) = (arrs.clone(), arrs[0].clone());
200 let result = arrs.remove_at(0).into_iter()
201 .fold(initial, |a, b| a.append(&b, axis).unwrap());
202 Ok(result)
203 }
204 }
205
206 fn stack(arrs: Vec<Self>, axis: Option<usize>) -> Result<Self, ArrayError> {
207 arrs.axis_opt_in_bounds(axis)?;
208 if arrs.is_empty() { Self::empty() }
209 else if (0..arrs.len() - 1).any(|i| arrs[i].get_shape() != arrs[i + 1].get_shape()) {
210 Err(ArrayError::ParameterError { param: "arrs", message: "all input arrays must have the same shape", })
211 } else {
212 let axis = axis.unwrap_or(0);
213 let new_shape = arrs[0].get_shape()?.insert_at(axis, arrs.len());
214
215 let (mut arrs, initial) = (arrs.clone(), arrs[0].clone());
216 arrs.remove_at(0).into_iter()
217 .fold(initial, |a, b| a.append(&b, Some(axis)).unwrap())
218 .reshape(&new_shape)
219 }
220 }
221
222 fn vstack(arrs: Vec<Self>) -> Result<Self, ArrayError> {
223 if arrs.is_empty() { Self::empty() }
224 else {
225 arrs.validate_stack_shapes(0, 0)?;
226
227 let mut new_shape = arrs[0].get_shape()?;
228 if new_shape.len() == 1 { new_shape.insert_at(0, arrs.len()); }
229 else { new_shape[0] = arrs.iter().fold(0, |a, b| a + b.shape[0]); }
230
231 match Self::concatenate(arrs, Some(0)) {
232 Ok(c) => c.reshape(&new_shape),
233 Err(e) => Err(e),
234 }
235 }
236 }
237
238 fn hstack(arrs: Vec<Self>) -> Result<Self, ArrayError> {
239 if arrs.is_empty() { return Self::empty() }
240 arrs.iter()
241 .map(Self::ndim)
242 .collect::<Vec<Result<usize, ArrayError>>>()
243 .has_error()?;
244 if arrs.iter().all(|arr| arr.ndim().unwrap() == 1) {
245 Self::concatenate(arrs, Some(0))
246 } else {
247 let arrs = arrs.iter()
248 .map(|arr| arr.atleast(2)).collect::<Vec<Result<Self, _>>>()
249 .has_error()?.into_iter()
250 .map(Result::unwrap)
251 .collect::<Vec<Self<>>>();
252 arrs.validate_stack_shapes(1, 0)?;
253
254 let mut new_shape = arrs[0].get_shape()?;
255 new_shape[1] = arrs.iter().fold(0, |a, b| a + b.shape[1]);
256
257 match Self::concatenate(arrs, Some(1)) {
258 Ok(c) => c.reshape(&new_shape),
259 Err(e) => Err(e),
260 }
261 }
262 }
263
264 fn dstack(arrs: Vec<Self>) -> Result<Self, ArrayError> {
265 if arrs.is_empty() { Self::empty() }
266 else {
267 let arrs = arrs.iter()
268 .map(|arr| arr.atleast(3))
269 .collect::<Vec<Result<Self, _>>>()
270 .has_error()?.into_iter()
271 .map(Result::unwrap)
272 .collect::<Vec<Self<>>>();
273 arrs.validate_stack_shapes(2, 0)?;
274
275 let mut new_shape = arrs[0].get_shape()?;
276 new_shape[2] = arrs.iter().fold(0, |a, b| a + b.shape[2]);
277
278 match Self::concatenate(arrs, Some(2)) {
279 Ok(c) => c.reshape(&new_shape),
280 Err(e) => Err(e),
281 }
282 }
283 }
284
285 fn column_stack(arrs: Vec<Self>) -> Result<Self, ArrayError> {
286 if arrs.is_empty() { Self::empty() }
287 else {
288 let (num_rows, mut total_cols) = (arrs[0].shape[0], 0);
289 arrs.is_dim_supported(&[1, 2])?;
290 if arrs.iter().any(|array| array.shape[0] != num_rows) {
291 return Err(ArrayError::ParameterError { param: "arrs", message: "all input arrays must have the same first dimension", });
292 }
293
294 arrs.iter()
295 .map(Self::ndim)
296 .collect::<Vec<Result<usize, ArrayError>>>()
297 .has_error()?;
298 for array in &arrs {
299 if array.ndim().unwrap() == 1 { total_cols += 1; }
300 else { total_cols += array.shape[1]; }
301 }
302
303 let (mut new_elements, mut new_col_idx) = (vec![T::zero(); num_rows * total_cols], 0);
304 for array in &arrs {
305 let array_cols = if array.ndim().unwrap() == 1 { 1 } else { array.shape[1] };
306 (0..num_rows).for_each(|row| {
307 (0..array_cols).for_each(|col| {
308 let src_idx = row * array_cols + col;
309 let dst_idx = row * total_cols + new_col_idx + col;
310 new_elements[dst_idx] = array.elements[src_idx].clone();
311 });
312 });
313 new_col_idx += array_cols;
314 }
315
316 Self::new(new_elements, vec![num_rows, total_cols])
317 }
318 }
319
320 fn row_stack(arrs: Vec<Self>) -> Result<Self, ArrayError> {
321 Self::vstack(arrs)
322 }
323}