#[repr(C, align(64))]pub struct Cube {
pub tables: Vec<Table>,
pub n_rows: Vec<usize>,
pub name: String,
pub third_dim_index: Option<Vec<String>>,
}Expand description
§Cube - 3D Type for Advanced Analysis Use Cases
Holds a vector of tables unified by some value, often Time,
for special indexing. Useful for data analysis.
§Purpose
Useful when the tables represent discrete time snapshots, or a category dimension. This enables comparing data without losing the underlying grain through aggregation, whilst still supporting that.
§Description
This is an optional extra enabled by the cube feature,
and is not part of the Apache Arrow framework.
§Under Development
⚠️ Unstable API and WIP: expect future development. Breaking changes will be minimised, but avoid using this in production unless you are ready to wear API adjustments.
Fields§
§tables: Vec<Table>Table entries forming the cube (rectangular prism)
n_rows: Vec<usize>Number of rows in each table
name: StringCube name
third_dim_index: Option<Vec<String>>Implementations§
Source§impl Cube
impl Cube
Sourcepub fn new(
name: String,
cols: Option<Vec<FieldArray>>,
third_dim_index: Option<Vec<String>>,
) -> Self
pub fn new( name: String, cols: Option<Vec<FieldArray>>, third_dim_index: Option<Vec<String>>, ) -> Self
Constructs a new Cube with a specified name and optional set of columns.
If cols is provided, the columns are used to create the first table.
The number of rows will be inferred from the first column.
If the name is empty or whitespace, a unique default name is assigned.
If no columns are provided, the Cube will be empty.
Examples found in repository?
402fn test_cube_broadcasting() {
403 #[cfg(feature = "cube")]
404 {
405 println!("┌─ Test 12: Cube (3D) Broadcasting");
406 println!("│ Operation: Cube{{2 tables}} + Cube{{2 tables}}");
407 println!("│ Expected: Element-wise addition across all tables");
408
409 // Create first cube with 2 tables
410 // First, create columns for table 1
411 let t1_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![1, 2]));
412 let t1_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![3, 4]));
413 let t1_fa1 = minarrow::FieldArray::from_arr("col1", t1_arr1);
414 let t1_fa2 = minarrow::FieldArray::from_arr("col2", t1_arr2);
415
416 // Create columns for cube1 via constructor
417 let mut cube1 = Cube::new("cube1".to_string(), Some(vec![t1_fa1, t1_fa2]), None);
418
419 // Add second table to cube1
420 let t2_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![5, 6]));
421 let t2_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![7, 8]));
422 let t2_fa1 = minarrow::FieldArray::from_arr("col1", t2_arr1);
423 let t2_fa2 = minarrow::FieldArray::from_arr("col2", t2_arr2);
424 let mut table2 = Table::new("t2".to_string(), None);
425 table2.add_col(t2_fa1);
426 table2.add_col(t2_fa2);
427 cube1.add_table(table2);
428
429 // Create second cube
430 let t3_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![10, 10]));
431 let t3_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![20, 20]));
432 let t3_fa1 = minarrow::FieldArray::from_arr("col1", t3_arr1);
433 let t3_fa2 = minarrow::FieldArray::from_arr("col2", t3_arr2);
434 let mut cube2 = Cube::new("cube2".to_string(), Some(vec![t3_fa1, t3_fa2]), None);
435
436 let t4_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![30, 30]));
437 let t4_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![40, 40]));
438 let t4_fa1 = minarrow::FieldArray::from_arr("col1", t4_arr1);
439 let t4_fa2 = minarrow::FieldArray::from_arr("col2", t4_arr2);
440 let mut table4 = Table::new("t4".to_string(), None);
441 table4.add_col(t4_fa1);
442 table4.add_col(t4_fa2);
443 cube2.add_table(table4);
444
445 match Value::Cube(Arc::new(cube1)) + Value::Cube(Arc::new(cube2)) {
446 Ok(Value::Cube(result)) => {
447 println!("│ Result cube with {} tables:", result.n_tables());
448 for i in 0..result.n_tables() {
449 println!("│ Table {}:", i);
450 if let Some(table) = result.table(i) {
451 for j in 0..table.n_cols() {
452 let col = &table.cols[j];
453 if let Array::NumericArray(NumericArray::Int32(arr)) = &col.array {
454 println!("│ Column {}: {:?}", j, arr.data.as_slice());
455 }
456 }
457 }
458 }
459 println!("└─ ✓ Passed\n");
460 }
461 Ok(other) => println!("└─ ✗ Error: Unexpected result type {:?}\n", other),
462 Err(e) => println!("└─ ✗ Error: {:?}\n", e),
463 }
464 }
465
466 #[cfg(not(feature = "cube"))]
467 {
468 println!("┌─ Test 12: Cube (3D) Broadcasting");
469 println!("└─ ⊘ Skipped (cube feature not enabled)\n");
470 }
471}Sourcepub fn add_table(&mut self, table: Table)
pub fn add_table(&mut self, table: Table)
Adds a table to the cube.
Examples found in repository?
402fn test_cube_broadcasting() {
403 #[cfg(feature = "cube")]
404 {
405 println!("┌─ Test 12: Cube (3D) Broadcasting");
406 println!("│ Operation: Cube{{2 tables}} + Cube{{2 tables}}");
407 println!("│ Expected: Element-wise addition across all tables");
408
409 // Create first cube with 2 tables
410 // First, create columns for table 1
411 let t1_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![1, 2]));
412 let t1_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![3, 4]));
413 let t1_fa1 = minarrow::FieldArray::from_arr("col1", t1_arr1);
414 let t1_fa2 = minarrow::FieldArray::from_arr("col2", t1_arr2);
415
416 // Create columns for cube1 via constructor
417 let mut cube1 = Cube::new("cube1".to_string(), Some(vec![t1_fa1, t1_fa2]), None);
418
419 // Add second table to cube1
420 let t2_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![5, 6]));
421 let t2_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![7, 8]));
422 let t2_fa1 = minarrow::FieldArray::from_arr("col1", t2_arr1);
423 let t2_fa2 = minarrow::FieldArray::from_arr("col2", t2_arr2);
424 let mut table2 = Table::new("t2".to_string(), None);
425 table2.add_col(t2_fa1);
426 table2.add_col(t2_fa2);
427 cube1.add_table(table2);
428
429 // Create second cube
430 let t3_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![10, 10]));
431 let t3_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![20, 20]));
432 let t3_fa1 = minarrow::FieldArray::from_arr("col1", t3_arr1);
433 let t3_fa2 = minarrow::FieldArray::from_arr("col2", t3_arr2);
434 let mut cube2 = Cube::new("cube2".to_string(), Some(vec![t3_fa1, t3_fa2]), None);
435
436 let t4_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![30, 30]));
437 let t4_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![40, 40]));
438 let t4_fa1 = minarrow::FieldArray::from_arr("col1", t4_arr1);
439 let t4_fa2 = minarrow::FieldArray::from_arr("col2", t4_arr2);
440 let mut table4 = Table::new("t4".to_string(), None);
441 table4.add_col(t4_fa1);
442 table4.add_col(t4_fa2);
443 cube2.add_table(table4);
444
445 match Value::Cube(Arc::new(cube1)) + Value::Cube(Arc::new(cube2)) {
446 Ok(Value::Cube(result)) => {
447 println!("│ Result cube with {} tables:", result.n_tables());
448 for i in 0..result.n_tables() {
449 println!("│ Table {}:", i);
450 if let Some(table) = result.table(i) {
451 for j in 0..table.n_cols() {
452 let col = &table.cols[j];
453 if let Array::NumericArray(NumericArray::Int32(arr)) = &col.array {
454 println!("│ Column {}: {:?}", j, arr.data.as_slice());
455 }
456 }
457 }
458 }
459 println!("└─ ✓ Passed\n");
460 }
461 Ok(other) => println!("└─ ✗ Error: Unexpected result type {:?}\n", other),
462 Err(e) => println!("└─ ✗ Error: {:?}\n", e),
463 }
464 }
465
466 #[cfg(not(feature = "cube"))]
467 {
468 println!("┌─ Test 12: Cube (3D) Broadcasting");
469 println!("└─ ⊘ Skipped (cube feature not enabled)\n");
470 }
471}Sourcepub fn schema(&self) -> Vec<Arc<Field>>
pub fn schema(&self) -> Vec<Arc<Field>>
Gets the schemea from the first table as representative of the rest
Sourcepub fn n_tables(&self) -> usize
pub fn n_tables(&self) -> usize
Returns the number of tables.
Examples found in repository?
402fn test_cube_broadcasting() {
403 #[cfg(feature = "cube")]
404 {
405 println!("┌─ Test 12: Cube (3D) Broadcasting");
406 println!("│ Operation: Cube{{2 tables}} + Cube{{2 tables}}");
407 println!("│ Expected: Element-wise addition across all tables");
408
409 // Create first cube with 2 tables
410 // First, create columns for table 1
411 let t1_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![1, 2]));
412 let t1_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![3, 4]));
413 let t1_fa1 = minarrow::FieldArray::from_arr("col1", t1_arr1);
414 let t1_fa2 = minarrow::FieldArray::from_arr("col2", t1_arr2);
415
416 // Create columns for cube1 via constructor
417 let mut cube1 = Cube::new("cube1".to_string(), Some(vec![t1_fa1, t1_fa2]), None);
418
419 // Add second table to cube1
420 let t2_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![5, 6]));
421 let t2_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![7, 8]));
422 let t2_fa1 = minarrow::FieldArray::from_arr("col1", t2_arr1);
423 let t2_fa2 = minarrow::FieldArray::from_arr("col2", t2_arr2);
424 let mut table2 = Table::new("t2".to_string(), None);
425 table2.add_col(t2_fa1);
426 table2.add_col(t2_fa2);
427 cube1.add_table(table2);
428
429 // Create second cube
430 let t3_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![10, 10]));
431 let t3_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![20, 20]));
432 let t3_fa1 = minarrow::FieldArray::from_arr("col1", t3_arr1);
433 let t3_fa2 = minarrow::FieldArray::from_arr("col2", t3_arr2);
434 let mut cube2 = Cube::new("cube2".to_string(), Some(vec![t3_fa1, t3_fa2]), None);
435
436 let t4_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![30, 30]));
437 let t4_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![40, 40]));
438 let t4_fa1 = minarrow::FieldArray::from_arr("col1", t4_arr1);
439 let t4_fa2 = minarrow::FieldArray::from_arr("col2", t4_arr2);
440 let mut table4 = Table::new("t4".to_string(), None);
441 table4.add_col(t4_fa1);
442 table4.add_col(t4_fa2);
443 cube2.add_table(table4);
444
445 match Value::Cube(Arc::new(cube1)) + Value::Cube(Arc::new(cube2)) {
446 Ok(Value::Cube(result)) => {
447 println!("│ Result cube with {} tables:", result.n_tables());
448 for i in 0..result.n_tables() {
449 println!("│ Table {}:", i);
450 if let Some(table) = result.table(i) {
451 for j in 0..table.n_cols() {
452 let col = &table.cols[j];
453 if let Array::NumericArray(NumericArray::Int32(arr)) = &col.array {
454 println!("│ Column {}: {:?}", j, arr.data.as_slice());
455 }
456 }
457 }
458 }
459 println!("└─ ✓ Passed\n");
460 }
461 Ok(other) => println!("└─ ✗ Error: Unexpected result type {:?}\n", other),
462 Err(e) => println!("└─ ✗ Error: {:?}\n", e),
463 }
464 }
465
466 #[cfg(not(feature = "cube"))]
467 {
468 println!("┌─ Test 12: Cube (3D) Broadcasting");
469 println!("└─ ⊘ Skipped (cube feature not enabled)\n");
470 }
471}Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if the cube is empty (no tables, no columns or no rows).
Sourcepub fn table(&self, idx: usize) -> Option<&Table>
pub fn table(&self, idx: usize) -> Option<&Table>
Returns a reference to a table by index.
Examples found in repository?
402fn test_cube_broadcasting() {
403 #[cfg(feature = "cube")]
404 {
405 println!("┌─ Test 12: Cube (3D) Broadcasting");
406 println!("│ Operation: Cube{{2 tables}} + Cube{{2 tables}}");
407 println!("│ Expected: Element-wise addition across all tables");
408
409 // Create first cube with 2 tables
410 // First, create columns for table 1
411 let t1_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![1, 2]));
412 let t1_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![3, 4]));
413 let t1_fa1 = minarrow::FieldArray::from_arr("col1", t1_arr1);
414 let t1_fa2 = minarrow::FieldArray::from_arr("col2", t1_arr2);
415
416 // Create columns for cube1 via constructor
417 let mut cube1 = Cube::new("cube1".to_string(), Some(vec![t1_fa1, t1_fa2]), None);
418
419 // Add second table to cube1
420 let t2_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![5, 6]));
421 let t2_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![7, 8]));
422 let t2_fa1 = minarrow::FieldArray::from_arr("col1", t2_arr1);
423 let t2_fa2 = minarrow::FieldArray::from_arr("col2", t2_arr2);
424 let mut table2 = Table::new("t2".to_string(), None);
425 table2.add_col(t2_fa1);
426 table2.add_col(t2_fa2);
427 cube1.add_table(table2);
428
429 // Create second cube
430 let t3_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![10, 10]));
431 let t3_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![20, 20]));
432 let t3_fa1 = minarrow::FieldArray::from_arr("col1", t3_arr1);
433 let t3_fa2 = minarrow::FieldArray::from_arr("col2", t3_arr2);
434 let mut cube2 = Cube::new("cube2".to_string(), Some(vec![t3_fa1, t3_fa2]), None);
435
436 let t4_arr1 = Array::from_int32(IntegerArray::from_slice(&vec64![30, 30]));
437 let t4_arr2 = Array::from_int32(IntegerArray::from_slice(&vec64![40, 40]));
438 let t4_fa1 = minarrow::FieldArray::from_arr("col1", t4_arr1);
439 let t4_fa2 = minarrow::FieldArray::from_arr("col2", t4_arr2);
440 let mut table4 = Table::new("t4".to_string(), None);
441 table4.add_col(t4_fa1);
442 table4.add_col(t4_fa2);
443 cube2.add_table(table4);
444
445 match Value::Cube(Arc::new(cube1)) + Value::Cube(Arc::new(cube2)) {
446 Ok(Value::Cube(result)) => {
447 println!("│ Result cube with {} tables:", result.n_tables());
448 for i in 0..result.n_tables() {
449 println!("│ Table {}:", i);
450 if let Some(table) = result.table(i) {
451 for j in 0..table.n_cols() {
452 let col = &table.cols[j];
453 if let Array::NumericArray(NumericArray::Int32(arr)) = &col.array {
454 println!("│ Column {}: {:?}", j, arr.data.as_slice());
455 }
456 }
457 }
458 }
459 println!("└─ ✓ Passed\n");
460 }
461 Ok(other) => println!("└─ ✗ Error: Unexpected result type {:?}\n", other),
462 Err(e) => println!("└─ ✗ Error: {:?}\n", e),
463 }
464 }
465
466 #[cfg(not(feature = "cube"))]
467 {
468 println!("┌─ Test 12: Cube (3D) Broadcasting");
469 println!("└─ ⊘ Skipped (cube feature not enabled)\n");
470 }
471}Sourcepub fn table_mut(&mut self, idx: usize) -> Option<&mut Table>
pub fn table_mut(&mut self, idx: usize) -> Option<&mut Table>
Returns a mutable reference to a table by index.
Sourcepub fn table_names(&self) -> Vec<&str>
pub fn table_names(&self) -> Vec<&str>
Returns the names of all tables in the cube.
Sourcepub fn table_index(&self, name: &str) -> Option<usize>
pub fn table_index(&self, name: &str) -> Option<usize>
Returns the index of a table by name.
Sourcepub fn remove_table_at(&mut self, idx: usize) -> bool
pub fn remove_table_at(&mut self, idx: usize) -> bool
Removes a table by index.
Sourcepub fn remove_table(&mut self, name: &str) -> bool
pub fn remove_table(&mut self, name: &str) -> bool
Removes a table by name.
Sourcepub fn tables_mut(&mut self) -> &mut [Table]
pub fn tables_mut(&mut self) -> &mut [Table]
Returns a mutable reference to all tables.
Sourcepub fn iter_tables(&self) -> Iter<'_, Table>
pub fn iter_tables(&self) -> Iter<'_, Table>
Returns an iterator over all tables.
pub fn iter_tables_mut(&mut self) -> IterMut<'_, Table>
Sourcepub fn col_index(&self, name: &str) -> Option<usize>
pub fn col_index(&self, name: &str) -> Option<usize>
Returns the index of a column by name (from the first table).
Sourcepub fn has_col(&self, name: &str) -> bool
pub fn has_col(&self, name: &str) -> bool
Returns true if the cube has a column of the given name (in all tables).
Sourcepub fn col(&self, idx: usize) -> Option<Vec<&FieldArray>>
pub fn col(&self, idx: usize) -> Option<Vec<&FieldArray>>
Returns all columns (FieldArrays) with the given index across all tables.
Sourcepub fn col_by_name(&self, name: &str) -> Option<Vec<&FieldArray>>
pub fn col_by_name(&self, name: &str) -> Option<Vec<&FieldArray>>
Returns all columns (FieldArrays) with the given name across all tables.
Sourcepub fn cols(&self) -> Vec<Vec<&FieldArray>>
pub fn cols(&self) -> Vec<Vec<&FieldArray>>
Returns all columns for all tables as Vec<Vec<&FieldArray>>.
Sourcepub fn remove_col(&mut self, name: &str) -> bool
pub fn remove_col(&mut self, name: &str) -> bool
Removes a column by name from all tables. Returns true if removed from all.
Sourcepub fn remove_col_at(&mut self, idx: usize) -> bool
pub fn remove_col_at(&mut self, idx: usize) -> bool
Removes a column by index from all tables. Returns true if removed from all.
Sourcepub fn iter_cols(
&self,
col_idx: usize,
) -> Option<impl Iterator<Item = &FieldArray>>
pub fn iter_cols( &self, col_idx: usize, ) -> Option<impl Iterator<Item = &FieldArray>>
Returns an iterator over the specified column across all tables.
Sourcepub fn iter_cols_by_name<'a>(
&'a self,
name: &'a str,
) -> Option<impl Iterator<Item = &'a FieldArray> + 'a>
pub fn iter_cols_by_name<'a>( &'a self, name: &'a str, ) -> Option<impl Iterator<Item = &'a FieldArray> + 'a>
Returns an iterator over the named column across all tables.
Sourcepub fn set_third_dim_index<S: Into<String>>(&mut self, cols: Vec<S>)
pub fn set_third_dim_index<S: Into<String>>(&mut self, cols: Vec<S>)
Sets the third dimensional index
Sourcepub fn third_dim_index(&self) -> Option<&[String]>
pub fn third_dim_index(&self) -> Option<&[String]>
Retrieves the third dimensional index
Sourcepub fn slice_clone(&self, offset: usize, len: usize) -> Self
pub fn slice_clone(&self, offset: usize, len: usize) -> Self
Returns a new owned Cube containing rows [offset, offset+len) for all tables.
Sourcepub fn slice(&self, offset: usize, len: usize) -> CubeV
pub fn slice(&self, offset: usize, len: usize) -> CubeV
Returns a zero-copy view over rows [offset, offset+len) for all tables.
Sourcepub fn par_iter_tables(&self) -> Iter<'_, Table>
pub fn par_iter_tables(&self) -> Iter<'_, Table>
Returns a parallel iterator over all tables.
Sourcepub fn par_iter_tables_mut(&mut self) -> IterMut<'_, Table>
pub fn par_iter_tables_mut(&mut self) -> IterMut<'_, Table>
Returns a parallel mutable iterator over all tables.
Trait Implementations§
Source§impl Concatenate for Cube
impl Concatenate for Cube
Source§fn concat(self, other: Self) -> Result<Self, MinarrowError>
fn concat(self, other: Self) -> Result<Self, MinarrowError>
Source§impl<'a> IntoIterator for &'a Cube
impl<'a> IntoIterator for &'a Cube
Source§impl<'a> IntoIterator for &'a mut Cube
impl<'a> IntoIterator for &'a mut Cube
Source§impl IntoIterator for Cube
impl IntoIterator for Cube
Source§impl Shape for Cube
impl Shape for Cube
impl StructuralPartialEq for Cube
Auto Trait Implementations§
impl Freeze for Cube
impl RefUnwindSafe for Cube
impl Send for Cube
impl Sync for Cube
impl Unpin for Cube
impl UnwindSafe for Cube
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> CustomValue for T
impl<T> CustomValue for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more