#[cfg(test)]
use std::collections::VecDeque;
use std::collections::{HashMap, HashSet};
use std::fmt::{self, Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use prettytable as pt;
#[cfg(feature = "serialize")]
use serde::ser::{Serialize, SerializeMap, Serializer};
use access::*;
use cons::*;
use error;
use field::{FieldData, Value};
use fieldlist::FieldPayloadCons;
#[cfg(test)]
use frame::StoreRefCount;
use frame::{Framed, IntoFrame, IntoMeltFrame, IntoStrFrame};
use join::*;
use label::*;
use partial::{DeriveCapabilities, Func, FuncDefault, Implemented, IsImplemented, PartialMap};
use permute::{
FilterPerm, SortOrder, SortOrderComparator, SortOrderUnstable, SortOrderUnstableComparator,
UpdatePermutation,
};
use select::{FieldSelect, SelectFieldByLabel};
use store::{IntoStore, IntoView};
pub(crate) type ViewFrameCons<FrameIndex, Frame, Tail> = LVCons<FrameIndex, Frame, Tail>;
pub(crate) type FrameLookupCons<Label, FrameIndex, FrameLabel, Tail> =
LMCons<Label, FrameDetailMarkers<FrameIndex, FrameLabel>, Tail>;
#[derive(Debug, Clone, Default)]
pub struct DataView<Labels, Frames> {
pub(crate) _labels: PhantomData<Labels>,
pub(crate) frames: Frames,
}
pub struct FrameDetailMarkers<FrameIndex, FrameLabel> {
_marker: PhantomData<(FrameIndex, FrameLabel)>,
}
pub trait FrameDetails {
type FrameIndex: Identifier;
type FrameLabel: Label;
}
impl<FrameIndex, FrameLabel> FrameDetails for FrameDetailMarkers<FrameIndex, FrameLabel>
where
FrameIndex: Identifier,
FrameLabel: Label,
{
type FrameIndex = FrameIndex;
type FrameLabel = FrameLabel;
}
impl<Labels, Frames> DataView<Labels, Frames> {
pub fn new(frames: Frames) -> DataView<Labels, Frames> {
DataView {
_labels: PhantomData,
frames,
}
}
}
impl<Labels, Frames> DataView<Labels, Frames> {
pub fn fieldnames<'a>(&'a self) -> Vec<&'a str>
where
Labels: StrLabels,
{
<Labels as StrLabels>::labels().into()
}
}
pub trait FrameIndexList {
type LabelList;
}
impl FrameIndexList for Nil {
type LabelList = Nil;
}
impl<Label, FrameIndex, FrameLabel, Tail> FrameIndexList
for FrameLookupCons<Label, FrameIndex, FrameLabel, Tail>
where
Tail: FrameIndexList,
{
type LabelList = LCons<FrameIndex, <Tail as FrameIndexList>::LabelList>;
}
impl<Labels, Frames> DataView<Labels, Frames>
where
Frames: Clone,
{
pub fn v<LabelList>(&self) -> <Self as Subview<LabelList>>::Output
where
Self: Subview<LabelList>,
{
Subview::<LabelList>::subview(self)
}
pub fn subview<LabelList>(&self) -> <Self as Subview<LabelList>>::Output
where
Self: Subview<LabelList>,
{
Subview::<LabelList>::subview(self)
}
}
pub trait Subview<LabelList> {
type Output;
fn subview(&self) -> Self::Output;
}
impl<Labels, Frames, LabelList> Subview<LabelList> for DataView<Labels, Frames>
where
Labels: FrameIndexList + HasLabels<LabelList> + LabelSubset<LabelList>,
<Labels as LabelSubset<LabelList>>::Output: Reorder<LabelList>,
Frames: Clone + SubsetClone<<Labels as FrameIndexList>::LabelList>,
{
type Output = DataView<
<<Labels as LabelSubset<LabelList>>::Output as Reorder<LabelList>>::Output,
<Frames as SubsetClone<<Labels as FrameIndexList>::LabelList>>::Output,
>;
fn subview(&self) -> Self::Output {
DataView {
_labels: PhantomData,
frames: self.frames.subset_clone(),
}
}
}
impl<Labels, Frames> NRows for DataView<Labels, Frames>
where
Frames: NRows,
{
fn nrows(&self) -> usize {
self.frames.nrows()
}
}
impl<Labels, Frames> DataView<Labels, Frames>
where
Self: NRows,
{
pub fn nrows(&self) -> usize {
NRows::nrows(self)
}
}
impl<Labels, Frames> DataView<Labels, Frames>
where
Labels: Len,
Frames: Len,
{
pub fn is_empty(&self) -> bool {
length![Labels] == 0 || Frames::is_empty()
}
}
impl<Labels, Frames> DataView<Labels, Frames>
where
Labels: Len,
{
pub fn nfields(&self) -> usize {
length![Labels]
}
}
impl<Labels, Frames> DataView<Labels, Frames>
where
Frames: Len,
{
pub fn nframes(&self) -> usize {
length![Frames]
}
}
#[cfg(test)]
pub trait StoreRefCounts {
fn store_ref_counts(&self) -> VecDeque<usize>;
}
#[cfg(test)]
impl StoreRefCounts for Nil {
fn store_ref_counts(&self) -> VecDeque<usize> {
VecDeque::new()
}
}
#[cfg(test)]
impl<FrameIndex, Frame, Tail> StoreRefCounts for ViewFrameCons<FrameIndex, Frame, Tail>
where
Frame: Valued,
ValueOf<Frame>: StoreRefCount,
Tail: StoreRefCounts,
{
fn store_ref_counts(&self) -> VecDeque<usize> {
let mut previous = self.tail.store_ref_counts();
previous.push_front(self.head.value_ref().store_ref_count());
previous
}
}
#[cfg(test)]
impl<Labels, Frames> DataView<Labels, Frames>
where
Frames: StoreRefCounts,
{
pub fn store_ref_counts(&self) -> VecDeque<usize> {
Frames::store_ref_counts(&self.frames)
}
}
pub trait FindFrameDetails<Label>: LookupMarkedElemByLabel<Label> {
type FrameDetails: FrameDetails;
}
impl<Labels, Label> FindFrameDetails<Label> for Labels
where
Labels: LookupMarkedElemByLabel<Label>,
MarkerOfElemOf<Labels, Label>: FrameDetails,
{
type FrameDetails = MarkerOfElemOf<Labels, Label>;
}
pub type FrameDetailsOf<Labels, Label> = <Labels as FindFrameDetails<Label>>::FrameDetails;
pub type FrameIndexOf<Labels, Label> =
<<Labels as FindFrameDetails<Label>>::FrameDetails as FrameDetails>::FrameIndex;
pub type FrameLabelOf<Labels, Label> =
<<Labels as FindFrameDetails<Label>>::FrameDetails as FrameDetails>::FrameLabel;
pub trait FindFrame<Labels, Label>: LookupValuedElemByLabel<FrameIndexOf<Labels, Label>>
where
Labels: FindFrameDetails<Label>,
{
}
impl<Frames, Labels, Label> FindFrame<Labels, Label> for Frames
where
Labels: FindFrameDetails<Label>,
Frames: LookupValuedElemByLabel<FrameIndexOf<Labels, Label>>,
{
}
pub type FrameElemByFrameIndexOf<Frames, FrameIndex> =
<Frames as LookupValuedElemByLabel<FrameIndex>>::Elem;
pub type FrameByFrameIndexOf<Frames, FrameIndex> =
<FrameElemByFrameIndexOf<Frames, FrameIndex> as Valued>::Value;
pub type FrameElemOf<Frames, Labels, Label> =
FrameElemByFrameIndexOf<Frames, FrameIndexOf<Labels, Label>>;
pub type FrameOf<Frames, Labels, Label> = <FrameElemOf<Frames, Labels, Label> as Valued>::Value;
pub type FieldFromFrameDetailsOf<Frames, FrameIndex, FrameLabel> =
<FrameByFrameIndexOf<Frames, FrameIndex> as SelectFieldByLabel<FrameLabel>>::Output;
pub type FieldTypeFromFrameDetailsOf<Frames, FrameIndex, FrameLabel> =
<FrameByFrameIndexOf<Frames, FrameIndex> as SelectFieldByLabel<FrameLabel>>::DType;
pub type FieldOf<Frames, Labels, Label> =
<FrameOf<Frames, Labels, Label> as SelectFieldByLabel<FrameLabelOf<Labels, Label>>>::Output;
pub type FieldTypeOf<Frames, Labels, Label> =
<FrameOf<Frames, Labels, Label> as SelectFieldByLabel<FrameLabelOf<Labels, Label>>>::DType;
pub type VFieldOf<View, Label> = <View as SelectFieldByLabel<Label>>::Output;
pub type VFieldTypeOf<View, Label> = <View as SelectFieldByLabel<Label>>::DType;
pub trait SelectFieldFromLabels<Labels, Label> {
type DType;
type Output: DataIndex<DType = Self::DType>;
fn select_field(&self) -> Self::Output;
}
impl<Labels, Frames, Label> SelectFieldFromLabels<Labels, Label> for Frames
where
Labels: FindFrameDetails<Label>,
Frames: FindFrame<Labels, Label>,
FrameOf<Frames, Labels, Label>: SelectFieldByLabel<FrameLabelOf<Labels, Label>>,
FieldOf<Frames, Labels, Label>: SelfValued + Clone,
FieldTypeOf<Frames, Labels, Label>: fmt::Debug,
{
type DType = FieldTypeOf<Frames, Labels, Label>;
type Output = FieldOf<Frames, Labels, Label>;
fn select_field(&self) -> Self::Output {
SelectFieldByLabel::<FrameLabelOf<Labels, Label>>::select_field(
LookupValuedElemByLabel::<FrameIndexOf<Labels, Label>>::elem(self).value_ref(),
)
.clone()
}
}
impl<Labels, Frames, Label> SelectFieldByLabel<Label> for DataView<Labels, Frames>
where
Frames: SelectFieldFromLabels<Labels, Label>,
{
type DType = <Frames as SelectFieldFromLabels<Labels, Label>>::DType;
type Output = <Frames as SelectFieldFromLabels<Labels, Label>>::Output;
fn select_field(&self) -> Self::Output {
SelectFieldFromLabels::<Labels, Label>::select_field(&self.frames)
}
}
impl<Labels, Frames> FieldSelect for DataView<Labels, Frames> {}
pub type DataIndexCons<Label, DType, DI, Tail> = FieldPayloadCons<Label, DType, DI, Tail>;
pub trait AssocDataIndexCons<Labels> {
type Output;
fn assoc_data(&self) -> Self::Output;
}
impl<Frames> AssocDataIndexCons<Nil> for Frames {
type Output = Nil;
fn assoc_data(&self) -> Nil {
Nil
}
}
impl<Label, FrameIndex, FrameLabel, LookupTail, Frames>
AssocDataIndexCons<FrameLookupCons<Label, FrameIndex, FrameLabel, LookupTail>> for Frames
where
Self: SelectFieldFromLabels<FrameLookupCons<Label, FrameIndex, FrameLabel, LookupTail>, Label>,
Self: AssocDataIndexCons<LookupTail>,
<Self as SelectFieldFromLabels<
FrameLookupCons<Label, FrameIndex, FrameLabel, LookupTail>,
Label,
>>::Output: Typed,
{
type Output = DataIndexCons<
Label,
TypeOf<
<Frames as SelectFieldFromLabels<
FrameLookupCons<Label, FrameIndex, FrameLabel, LookupTail>,
Label,
>>::Output,
>,
<Frames as SelectFieldFromLabels<
FrameLookupCons<Label, FrameIndex, FrameLabel, LookupTail>,
Label,
>>::Output,
<Frames as AssocDataIndexCons<LookupTail>>::Output,
>;
fn assoc_data(&self) -> Self::Output {
DataIndexCons {
head: TypedValue::from(SelectFieldFromLabels::<
FrameLookupCons<Label, FrameIndex, FrameLabel, LookupTail>,
Label,
>::select_field(self))
.into(),
tail: AssocDataIndexCons::<LookupTail>::assoc_data(self),
}
}
}
pub type AssocDataIndexConsOf<Labels, Frames> = <Frames as AssocDataIndexCons<Labels>>::Output;
const MAX_DISP_ROWS: usize = 1000;
impl<Labels, Frames> Display for DataView<Labels, Frames>
where
Frames: Len + NRows + AssocDataIndexCons<Labels>,
AssocDataIndexConsOf<Labels, Frames>: DeriveCapabilities<AddCellToRowFn>,
Labels: StrLabels,
{
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
if Frames::is_empty() {
return write!(f, "Empty DataView");
}
let mut table = pt::Table::new();
let nrows = self.nrows();
let mut func = AddCellToRowFn {
rows: vec![pt::row::Row::empty(); nrows.min(MAX_DISP_ROWS)],
};
self.frames.assoc_data().derive().map(&mut func);
for row in func.rows.drain(..) {
table.add_row(row);
}
table.set_titles(<Labels as StrLabels>::labels().into());
table.set_format(*pt::format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
Display::fmt(&table, f)
}
}
pub struct AddCellToRowFn {
rows: Vec<pt::row::Row>,
}
impl<DType> Func<DType> for AddCellToRowFn
where
for<'a> Value<&'a DType>: ToString,
{
type Output = ();
fn call<DI>(&mut self, data: &DI) -> Self::Output
where
DI: DataIndex<DType = DType>,
{
debug_assert!(data.len() >= self.rows.len());
for i in 0..self.rows.len() {
self.rows[i].add_cell(cell!(data.get_datum(i).unwrap()));
}
}
}
impl FuncDefault for AddCellToRowFn {
type Output = ();
fn call(&mut self) -> Self::Output {
for i in 0..self.rows.len() {
self.rows[i].add_cell(cell!());
}
}
}
macro_rules! impl_addcell_is_impl {
($($dtype:ty)*) => {$(
impl IsImplemented<AddCellToRowFn> for $dtype {
type IsImpl = Implemented;
}
)*}
}
impl_addcell_is_impl![String &str f64 f32 u64 u32 i64 i32 bool];
impl<Labels, Frames> DataView<Labels, Frames> {
pub fn relabel<CurrLabel, NewLabel>(
self,
) -> DataView<<Labels as Relabel<CurrLabel, NewLabel>>::Output, Frames>
where
Labels: Relabel<CurrLabel, NewLabel>,
{
DataView {
_labels: PhantomData,
frames: self.frames,
}
}
}
pub trait Relabel<TargetLabel, NewLabel> {
type Output;
}
impl<TargetLabel, NewLabel, Label, FrameIndex, FrameLabel, Tail> Relabel<TargetLabel, NewLabel>
for FrameLookupCons<Label, FrameIndex, FrameLabel, Tail>
where
TargetLabel: LabelEq<Label>,
FrameLookupCons<Label, FrameIndex, FrameLabel, Tail>:
RelabelMatch<TargetLabel, NewLabel, <TargetLabel as LabelEq<Label>>::Eq>,
{
type Output = <FrameLookupCons<Label, FrameIndex, FrameLabel, Tail> as RelabelMatch<
TargetLabel,
NewLabel,
<TargetLabel as LabelEq<Label>>::Eq,
>>::Output;
}
pub trait RelabelMatch<TargetLabel, NewLabel, Match> {
type Output;
}
impl<TargetLabel, NewLabel, Label, FrameIndex, FrameLabel, Tail>
RelabelMatch<TargetLabel, NewLabel, True>
for FrameLookupCons<Label, FrameIndex, FrameLabel, Tail>
{
type Output = FrameLookupCons<NewLabel, FrameIndex, FrameLabel, Tail>;
}
impl<TargetLabel, NewLabel, Label, FrameIndex, FrameLabel, Tail>
RelabelMatch<TargetLabel, NewLabel, False>
for FrameLookupCons<Label, FrameIndex, FrameLabel, Tail>
where
Tail: Relabel<TargetLabel, NewLabel>,
{
type Output = FrameLookupCons<
Label,
FrameIndex,
FrameLabel,
<Tail as Relabel<TargetLabel, NewLabel>>::Output,
>;
}
pub trait ViewMerge<Other> {
type Output;
fn merge(&self, right: &Other) -> error::Result<Self::Output>;
}
impl<Labels, Frames, RLabels, RFrames> ViewMerge<DataView<RLabels, RFrames>>
for DataView<Labels, Frames>
where
Self: Merge<RLabels, RFrames>,
RFrames: NRows,
Frames: NRows,
<Self as Merge<RLabels, RFrames>>::OutLabels: IsLabelSet<IsSet = True>,
{
type Output = DataView<
<Self as Merge<RLabels, RFrames>>::OutLabels,
<Self as Merge<RLabels, RFrames>>::OutFrames,
>;
fn merge(&self, right: &DataView<RLabels, RFrames>) -> error::Result<Self::Output> {
if self.nrows() != right.nrows() {
return Err(error::AgnesError::DimensionMismatch(
"number of rows mismatch in merge".into(),
));
}
Ok(Merge::merge(self, right))
}
}
impl<Labels, Frames> DataView<Labels, Frames> {
pub fn merge<RLabels, RFrames>(
&self,
right: &DataView<RLabels, RFrames>,
) -> error::Result<<Self as ViewMerge<DataView<RLabels, RFrames>>>::Output>
where
Self: ViewMerge<DataView<RLabels, RFrames>>,
{
ViewMerge::merge(self, right)
}
}
impl<Labels, Frames> DataView<Labels, Frames> {
pub fn join<Join, RLabels, RFrames>(
&self,
right: &DataView<RLabels, RFrames>,
) -> <Self as SortMergeJoin<RLabels, RFrames, Join>>::Output
where
Self: SortMergeJoin<RLabels, RFrames, Join>,
{
SortMergeJoin::join(self, right)
}
}
impl<FrameIndex, Frame, Tail> UpdatePermutation for ViewFrameCons<FrameIndex, Frame, Tail>
where
Frame: Valued<Value = Frame>,
ValueOf<Frame>: UpdatePermutation,
Tail: UpdatePermutation,
{
fn update_permutation(mut self, order: &[usize]) -> Self {
self.head = Labeled::from(self.head.value().update_permutation(order));
self.tail = self.tail.update_permutation(order);
self
}
}
impl<Labels, Frames> DataView<Labels, Frames>
where
Frames: UpdatePermutation,
{
pub fn sort_by_label<Label>(mut self) -> Self
where
Self: SelectFieldByLabel<Label>,
<Self as SelectFieldByLabel<Label>>::Output: SortOrder,
{
let sorted = self.field::<Label>().sort_order();
self.frames = self.frames.update_permutation(&sorted);
self
}
pub fn sort_unstable_by_label<Label>(mut self) -> Self
where
Self: SelectFieldByLabel<Label>,
<Self as SelectFieldByLabel<Label>>::Output: SortOrderUnstable,
{
let sorted = self.field::<Label>().sort_order_unstable();
self.frames = self.frames.update_permutation(&sorted);
self
}
pub fn sort_by_label_comparator<Label, F>(mut self, compare: F) -> Self
where
Self: SelectFieldByLabel<Label>,
<Self as SelectFieldByLabel<Label>>::Output: SortOrderComparator<F>,
{
let sorted = self.field::<Label>().sort_order_by(compare);
self.frames = self.frames.update_permutation(&sorted);
self
}
pub fn sort_unstable_by_label_comparator<Label, F>(mut self, compare: F) -> Self
where
Self: SelectFieldByLabel<Label>,
<Self as SelectFieldByLabel<Label>>::Output: SortOrderUnstableComparator<F>,
{
let sorted = self.field::<Label>().sort_order_unstable_by(compare);
self.frames = self.frames.update_permutation(&sorted);
self
}
pub fn filter<Label, P>(mut self, predicate: P) -> Self
where
Self: SelectFieldByLabel<Label>,
<Self as SelectFieldByLabel<Label>>::Output: FilterPerm<P>,
{
let perm = self.field::<Label>().filter_perm(predicate);
self.frames = self.frames.update_permutation(&perm);
self
}
}
pub trait FieldList<LabelList, Frames> {
type Output;
fn field_list(frames: &Frames) -> Self::Output;
}
impl<LabelList, Frames> FieldList<LabelList, Frames> for Nil {
type Output = Nil;
fn field_list(_frames: &Frames) -> Nil {
Nil
}
}
impl<LabelList, Frames, Label, FrameIndex, FrameLabel, Tail> FieldList<LabelList, Frames>
for FrameLookupCons<Label, FrameIndex, FrameLabel, Tail>
where
LabelList: Member<Label>,
Self: FieldListPred<LabelList, Frames, <LabelList as Member<Label>>::IsMember>,
{
type Output =
<Self as FieldListPred<LabelList, Frames, <LabelList as Member<Label>>::IsMember>>::Output;
fn field_list(frames: &Frames) -> Self::Output {
Self::field_list_pred(frames)
}
}
pub trait FieldListPred<LabelList, Frames, IsMember> {
type Output;
fn field_list_pred(frames: &Frames) -> Self::Output;
}
impl<LabelList, Frames, Label, FrameIndex, FrameLabel, Tail> FieldListPred<LabelList, Frames, True>
for FrameLookupCons<Label, FrameIndex, FrameLabel, Tail>
where
Frames: SelectFieldFromLabels<Self, Label>,
Tail: FieldList<LabelList, Frames>,
{
type Output = Cons<
<Frames as SelectFieldFromLabels<
FrameLookupCons<Label, FrameIndex, FrameLabel, Tail>,
Label,
>>::Output,
<Tail as FieldList<LabelList, Frames>>::Output,
>;
fn field_list_pred(frames: &Frames) -> Self::Output {
Cons {
head: SelectFieldFromLabels::<Self, Label>::select_field(frames),
tail: Tail::field_list(frames),
}
}
}
impl<LabelList, Frames, Label, FrameIndex, FrameLabel, Tail> FieldListPred<LabelList, Frames, False>
for FrameLookupCons<Label, FrameIndex, FrameLabel, Tail>
where
Tail: FieldList<LabelList, Frames>,
{
type Output = <Tail as FieldList<LabelList, Frames>>::Output;
fn field_list_pred(frames: &Frames) -> Self::Output {
Tail::field_list(frames)
}
}
#[derive(Debug, Clone)]
pub struct Record<'a, Fields> {
fields: &'a Fields,
idx: usize,
}
impl<'a, Fields> Record<'a, Fields> {
fn new(field_list: &'a Fields, idx: usize) -> Record<'a, Fields> {
Record {
fields: field_list,
idx,
}
}
}
pub trait HashIndex {
fn hash_index<H>(&self, idx: usize, state: &mut H)
where
H: Hasher;
}
impl<T, DI> HashIndex for Framed<T, DI>
where
for<'a> Value<&'a T>: Hash,
Self: DataIndex<DType = T>,
{
fn hash_index<H>(&self, idx: usize, state: &mut H)
where
H: Hasher,
{
self.get_datum(idx).unwrap().hash(state);
}
}
impl HashIndex for Nil {
fn hash_index<H>(&self, _idx: usize, _state: &mut H)
where
H: Hasher,
{
}
}
impl<Head, Tail> HashIndex for Cons<Head, Tail>
where
Head: HashIndex,
Tail: HashIndex,
{
fn hash_index<H>(&self, idx: usize, state: &mut H)
where
H: Hasher,
{
self.head.hash_index(idx, state);
self.tail.hash_index(idx, state);
}
}
impl<'a, Fields> Hash for Record<'a, Fields>
where
Fields: HashIndex,
{
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.fields.hash_index(self.idx, state)
}
}
pub trait PartialEqIndex {
fn eq_index(&self, other: &Self, idx: usize) -> bool;
}
impl<T, DI> PartialEqIndex for Framed<T, DI>
where
for<'a> Value<&'a T>: PartialEq,
Self: DataIndex<DType = T>,
{
fn eq_index(&self, other: &Self, idx: usize) -> bool {
self.get_datum(idx)
.unwrap()
.eq(&other.get_datum(idx).unwrap())
}
}
impl PartialEqIndex for Nil {
fn eq_index(&self, _other: &Nil, _idx: usize) -> bool {
true
}
}
impl<Head, Tail> PartialEqIndex for Cons<Head, Tail>
where
Head: PartialEqIndex,
Tail: PartialEqIndex,
{
fn eq_index(&self, other: &Self, idx: usize) -> bool {
self.head.eq_index(&other.head, idx) && self.tail.eq_index(&other.tail, idx)
}
}
impl<'a, Fields> PartialEq for Record<'a, Fields>
where
Fields: PartialEqIndex,
{
fn eq(&self, other: &Self) -> bool {
self.fields.eq_index(other.fields, self.idx)
}
}
impl<'a, Fields> Eq for Record<'a, Fields> where Self: PartialEq {}
impl<'a> Display for Record<'a, Nil> {
fn fmt(&self, _f: &mut Formatter) -> Result<(), fmt::Error> {
Ok(())
}
}
impl<'a, Head, Tail> Display for Record<'a, Cons<Head, Tail>>
where
Head: DataIndex,
<Head as DataIndex>::DType: Display,
Record<'a, Tail>: Display,
{
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "{},", self.fields.head.get_datum(self.idx).unwrap())?;
Record {
fields: &self.fields.tail,
idx: self.idx,
}
.fmt(f)
}
}
impl<Labels, Frames> DataView<Labels, Frames> {
pub fn field_list<LabelList>(&self) -> <Labels as FieldList<LabelList, Frames>>::Output
where
Labels: FieldList<LabelList, Frames>,
{
<Labels as FieldList<LabelList, Frames>>::field_list(&self.frames)
}
pub fn unique_indices<LabelList>(&self) -> Vec<usize>
where
Self: Unique<LabelList>,
{
Unique::<LabelList>::unique_indices(self)
}
pub fn unique_values<LabelList>(&self) -> <Self as Unique<LabelList>>::Output
where
Self: Unique<LabelList>,
{
Unique::<LabelList>::unique_values(self)
}
}
pub trait Unique<LabelList> {
type Output;
fn unique_indices(&self) -> Vec<usize>;
fn unique_values(&self) -> Self::Output;
}
impl<Labels, Frames, LabelList> Unique<LabelList> for DataView<Labels, Frames>
where
Labels: FieldList<LabelList, Frames>
+ HasLabels<LabelList>
+ LabelSubset<LabelList>
+ FrameIndexList,
<Labels as FieldList<LabelList, Frames>>::Output: HashIndex + PartialEqIndex,
<Labels as LabelSubset<LabelList>>::Output: Reorder<LabelList>,
Frames: NRows + SubsetClone<<Labels as FrameIndexList>::LabelList>,
<Frames as SubsetClone<<Labels as FrameIndexList>::LabelList>>::Output: UpdatePermutation,
{
type Output = DataView<
<<Labels as LabelSubset<LabelList>>::Output as Reorder<LabelList>>::Output,
<Frames as SubsetClone<<Labels as FrameIndexList>::LabelList>>::Output,
>;
fn unique_indices(&self) -> Vec<usize> {
let fl = self.field_list::<LabelList>();
let mut indices = vec![];
let mut set = HashSet::new();
for i in 0..self.nrows() {
let record = Record::new(&fl, i);
if !set.contains(&record) {
set.insert(record);
indices.push(i);
}
}
indices
}
fn unique_values(&self) -> Self::Output {
let indices = self.unique_indices::<LabelList>();
let new_frames = self.frames.subset_clone().update_permutation(&indices);
DataView {
_labels: PhantomData,
frames: new_frames,
}
}
}
#[cfg(feature = "serialize")]
impl<Labels, Frames> Serialize for DataView<Labels, Frames>
where
Labels: Len + SerializeViewField<Frames>,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let map = serializer.serialize_map(Some(self.nfields()))?;
Labels::serialize_view_field(&self.frames, map)
}
}
#[cfg(feature = "serialize")]
pub trait SerializeViewField<Frames> {
fn serialize_view_field<M>(frames: &Frames, map: M) -> Result<M::Ok, M::Error>
where
M: SerializeMap;
}
#[cfg(feature = "serialize")]
impl<Frames> SerializeViewField<Frames> for Nil {
fn serialize_view_field<M>(_frames: &Frames, map: M) -> Result<M::Ok, M::Error>
where
M: SerializeMap,
{
map.end()
}
}
#[cfg(feature = "serialize")]
impl<Frames, Label, FrameIndex, FrameLabel, Tail> SerializeViewField<Frames>
for FrameLookupCons<Label, FrameIndex, FrameLabel, Tail>
where
Frames: SelectFieldFromLabels<Self, Label>,
<Frames as SelectFieldFromLabels<Self, Label>>::Output: Serialize,
Label: LabelName,
Tail: SerializeViewField<Frames>,
{
fn serialize_view_field<M>(frames: &Frames, mut map: M) -> Result<M::Ok, M::Error>
where
M: SerializeMap,
{
map.serialize_entry(
Label::name(),
&SelectFieldFromLabels::<Self, Label>::select_field(frames),
)?;
Tail::serialize_view_field(frames, map)
}
}
impl<Labels, Frames> DataView<Labels, Frames> {
pub fn melt<MeltLabels, NameLabel, ValueLabel, HoldLabels>(
&self,
) -> <Self as Melt<MeltLabels, NameLabel, ValueLabel, HoldLabels>>::Output
where
Self: Melt<MeltLabels, NameLabel, ValueLabel, HoldLabels>,
{
Melt::<MeltLabels, NameLabel, ValueLabel, HoldLabels>::melt(self)
}
}
pub trait Melt<MeltLabels, NameLabel, ValueLabel, HoldLabels> {
type Output;
fn melt(&self) -> Self::Output;
}
type AsView<Orig> = <Orig as IntoView>::Output;
type AsFrame<Orig> = <Orig as IntoFrame>::Output;
type AsMeltFrame<Orig, ValueLabel> = <Orig as IntoMeltFrame<ValueLabel>>::Output;
type WithFrame<Orig, Added> = <Orig as AddFrame<Added>>::Output;
impl<Frames, Labels, MeltLabels, NameLabel, ValueLabel, HoldLabels>
Melt<MeltLabels, NameLabel, ValueLabel, HoldLabels> for DataView<Labels, Frames>
where
Frames: NRows + Clone,
NameLabel: Debug,
Labels: SetDiff<MeltLabels, Set = HoldLabels>,
MeltLabels: Len + IntoStrFrame<NameLabel>,
<MeltLabels as IntoStrFrame<NameLabel>>::Output: IntoView,
Self: Subview<HoldLabels>,
<Self as Subview<HoldLabels>>::Output: IntoFrame,
<<Self as Subview<HoldLabels>>::Output as IntoFrame>::Output: UpdatePermutation,
AsView<<MeltLabels as IntoStrFrame<NameLabel>>::Output>:
AddFrame<<<Self as Subview<HoldLabels>>::Output as IntoFrame>::Output>,
Self: Subview<MeltLabels>,
<Self as Subview<MeltLabels>>::Output: IntoMeltFrame<ValueLabel>,
WithFrame<
AsView<<MeltLabels as IntoStrFrame<NameLabel>>::Output>,
AsFrame<<Self as Subview<HoldLabels>>::Output>,
>: AddFrame<AsMeltFrame<<Self as Subview<MeltLabels>>::Output, ValueLabel>>,
HoldLabels: AssocLabels,
<HoldLabels as AssocLabels>::Labels: Append<Labels![NameLabel, ValueLabel]>,
WithFrame<
WithFrame<
AsView<<MeltLabels as IntoStrFrame<NameLabel>>::Output>,
AsFrame<<Self as Subview<HoldLabels>>::Output>,
>,
AsMeltFrame<<Self as Subview<MeltLabels>>::Output, ValueLabel>,
>: Subview<
<<HoldLabels as AssocLabels>::Labels as Append<Labels![NameLabel, ValueLabel]>>::Appended,
>,
{
type Output = <WithFrame<
WithFrame<
AsView<<MeltLabels as IntoStrFrame<NameLabel>>::Output>,
AsFrame<<Self as Subview<HoldLabels>>::Output>,
>,
AsMeltFrame<<Self as Subview<MeltLabels>>::Output, ValueLabel>,
> as Subview<
<<HoldLabels as AssocLabels>::Labels as Append<Labels![NameLabel, ValueLabel]>>::Appended,
>>::Output;
fn melt(&self) -> Self::Output {
let premelt_nrows = self.nrows();
let melt_len = MeltLabels::len();
let melt_label_view = MeltLabels::into_repeated_str_frame(premelt_nrows).into_view();
let hold_frame = Subview::<HoldLabels>::subview(self).into_frame();
let mut hold_permutation = Vec::with_capacity(melt_len * premelt_nrows);
for i in 0..premelt_nrows {
for _ in 0..melt_len {
hold_permutation.push(i);
}
}
let hold_frame = hold_frame.update_permutation(&hold_permutation);
let label_hold_dv = melt_label_view.add_frame(hold_frame);
let melt_frame =
IntoMeltFrame::<ValueLabel>::into_melt_frame(Subview::<MeltLabels>::subview(self));
let final_dv = label_hold_dv.add_frame(melt_frame);
final_dv.subview()
}
}
impl<Labels, Frames> DataView<Labels, Frames> {
pub fn aggregate<KeyLabels, ValueLabel, AggLabel, DType, AggType, AggFunc>(
&self,
init: AggType,
f: AggFunc,
) -> <Self as Aggregate<KeyLabels, ValueLabel, AggLabel, DType, AggType>>::Output
where
Self: Aggregate<KeyLabels, ValueLabel, AggLabel, DType, AggType>,
AggFunc: Fn(&mut AggType, Value<&DType>),
{
Aggregate::<KeyLabels, ValueLabel, AggLabel, DType, AggType>::aggregate::<AggFunc>(
self, init, f,
)
}
}
pub trait Aggregate<KeyLabels, ValueLabel, AggLabel, DType, AggType> {
type Output;
fn aggregate<AggFunc>(&self, init: AggType, f: AggFunc) -> Self::Output
where
AggFunc: Fn(&mut AggType, Value<&DType>);
}
impl<Labels, Frames, KeyLabels, ValueLabel, AggLabel, DType, AggType>
Aggregate<KeyLabels, ValueLabel, AggLabel, DType, AggType> for DataView<Labels, Frames>
where
Self: NRows + SelectFieldByLabel<ValueLabel, DType = DType>,
Labels: FieldList<KeyLabels, Frames> + LabelSubset<KeyLabels> + FrameIndexList,
<Labels as FieldList<KeyLabels, Frames>>::Output: HashIndex + PartialEqIndex,
<Labels as LabelSubset<KeyLabels>>::Output: Reorder<KeyLabels>,
AggType: Clone,
FieldData<AggType>: IntoStore<AggLabel>,
<FieldData<AggType> as IntoStore<AggLabel>>::Output: IntoFrame,
Frames: NRows + SubsetClone<<Labels as FrameIndexList>::LabelList>,
<Frames as SubsetClone<<Labels as FrameIndexList>::LabelList>>::Output: UpdatePermutation,
DataView<
<<Labels as LabelSubset<KeyLabels>>::Output as Reorder<KeyLabels>>::Output,
<Frames as SubsetClone<<Labels as FrameIndexList>::LabelList>>::Output,
>: AddFrame<<<FieldData<AggType> as IntoStore<AggLabel>>::Output as IntoFrame>::Output>,
{
type Output = <DataView<
<<Labels as LabelSubset<KeyLabels>>::Output as Reorder<KeyLabels>>::Output,
<Frames as SubsetClone<<Labels as FrameIndexList>::LabelList>>::Output,
> as AddFrame<
<<FieldData<AggType> as IntoStore<AggLabel>>::Output as IntoFrame>::Output,
>>::Output;
fn aggregate<AggFunc>(&self, init: AggType, f: AggFunc) -> Self::Output
where
AggFunc: Fn(&mut AggType, Value<&DType>),
{
let fl = self.field_list::<KeyLabels>();
let values = self.field::<ValueLabel>();
let mut map = HashMap::new();
let mut indices = vec![];
let mut aggregates = vec![];
for i in 0..self.nrows() {
let record = Record::new(&fl, i);
let aggregates_idx = map.entry(record).or_insert_with(|| {
indices.push(i);
aggregates.push(init.clone());
debug_assert_eq!(indices.len(), aggregates.len());
indices.len() - 1
});
f(
&mut aggregates[*aggregates_idx],
values.get_datum(i).unwrap(),
);
}
let agg_data: FieldData<_> = aggregates.into();
let agg_frame = IntoStore::<AggLabel>::into_store(agg_data).into_frame();
let record_frames = self.frames.subset_clone().update_permutation(&indices);
DataView {
_labels: PhantomData,
frames: record_frames,
}
.add_frame(agg_frame)
}
}
#[cfg(test)]
mod tests {
use std::fmt::Debug;
use std::path::Path;
use csv_sniffer::metadata::Metadata;
use super::*;
use source::csv::{CsvReader, CsvSource, IntoCsvSrcSchema};
#[cfg(feature = "test-utils")]
use test_utils::*;
use access::DataIndex;
use error::*;
fn load_csv_file<Schema>(
filename: &str,
schema: Schema,
) -> (CsvReader<Schema::CsvSrcSchema>, Metadata)
where
Schema: IntoCsvSrcSchema,
<Schema as IntoCsvSrcSchema>::CsvSrcSchema: Debug,
{
let data_filepath = Path::new(file!())
.parent()
.unwrap()
.parent()
.unwrap()
.join("tests")
.join("data")
.join(filename);
let source = CsvSource::new(data_filepath).unwrap();
(
CsvReader::new(&source, schema).unwrap(),
source.metadata().clone(),
)
}
tablespace![
pub table gdp {
CountryName: String,
CountryCode: String,
Year1983: f64,
}
];
#[test]
fn lookup_field() {
let gdp_schema = schema![
fieldname gdp::CountryName = "Country Name";
fieldname gdp::CountryCode = "Country Code";
fieldname gdp::Year1983 = "1983";
];
let (mut csv_rdr, _metadata) = load_csv_file("gdp.csv", gdp_schema.clone());
let ds = csv_rdr.read().unwrap();
let view = ds.into_view();
let country_name = view.field::<gdp::CountryName>();
println!("{:?}", country_name);
}
#[test]
fn generate_dataindex_cons() {
let gdp_schema = schema![
fieldname gdp::CountryName = "Country Name";
fieldname gdp::CountryCode = "Country Code";
fieldname gdp::Year1983 = "1983";
];
let (mut csv_rdr, _metadata) = load_csv_file("gdp.csv", gdp_schema.clone());
let ds = csv_rdr.read().unwrap();
let view = ds.into_view();
println!("{}", view);
}
#[cfg(feature = "test-utils")]
#[test]
fn merge() {
let dv1 = sample_emp_table().into_view();
let dv2 = sample_emp_table_extra().into_view();
println!("{}", dv1);
println!("{}", dv2);
let merged_dv = dv1.merge(&dv2).unwrap();
println!("{}", merged_dv);
assert_eq!(merged_dv.nrows(), 7);
assert_eq!(merged_dv.nfields(), 6);
assert_eq!(
merged_dv.fieldnames(),
vec![
"EmpId",
"DeptId",
"EmpName",
"SalaryOffset",
"DidTraining",
"VacationHrs"
]
);
}
#[cfg(feature = "test-utils")]
#[test]
fn merge_dimension_mismatch() {
let dv1 = sample_emp_table().into_view();
let dv2 = sample_dept_table().into_view();
println!("{}", dv1);
println!("{}", dv2);
let merge_result = dv1.merge(&dv2);
match merge_result {
Ok(_) => {
panic!("Merge was expected to fail (dimension mismatch), but succeeded");
}
Err(AgnesError::DimensionMismatch(_)) => { }
Err(e) => {
panic!("Incorrect error: {:?}", e);
}
};
}
#[cfg(feature = "test-utils")]
tablespace![
@continue(typenum::Add1<::test_utils::emp_table::Table>)
pub table emp_table2 {
EmpId: u64,
DeptId: u64,
EmpName: String,
}
];
#[cfg(feature = "test-utils")]
#[test]
fn merge_different_stores() {
let dv1 = sample_emp_table().into_view();
let ds2: emp_table2::Store = sample_emp_table![];
let dv2 = ds2.into_view();
println!("{}", dv1);
println!("{}", dv2);
let merged_dv = dv1.merge(&dv2).unwrap();
println!("{}", merged_dv);
assert_eq!(merged_dv.nrows(), 7);
assert_eq!(merged_dv.nfields(), 6);
assert_eq!(
merged_dv.fieldnames(),
vec!["EmpId", "DeptId", "EmpName", "EmpId", "DeptId", "EmpName"]
);
}
#[cfg(feature = "test-utils")]
tablespace![
@continue(typenum::Add1<::view::tests::emp_table2::Table>)
pub table emp_table3 {
EmployeeId: u64,
DepartmentId: u64,
EmployeeName: String,
}
];
#[cfg(feature = "test-utils")]
#[test]
fn relabel() {
let dv1 = sample_emp_table().into_view();
let dv2 = sample_emp_table().into_view();
let dv1 = dv1.relabel::<emp_table::EmpId, emp_table3::EmployeeId>();
let dv1 = dv1.relabel::<emp_table::DeptId, emp_table3::DepartmentId>();
let dv1 = dv1.relabel::<emp_table::EmpName, emp_table3::EmployeeName>();
let merged_dv = dv1.merge(&dv2).unwrap();
println!("{}", merged_dv);
assert_eq!(merged_dv.nrows(), 7);
assert_eq!(merged_dv.nfields(), 6);
assert_eq!(
merged_dv.fieldnames(),
vec![
"EmployeeId",
"DepartmentId",
"EmployeeName",
"EmpId",
"DeptId",
"EmpName"
]
);
}
#[cfg(feature = "test-utils")]
tablespace![
@continue(typenum::Add1<::view::tests::emp_table3::Table>)
pub table emp_table4 {
EmplId: u64 = {"Employee Id"},
DeptId: u64 = {"Department Id"},
EmpName: String = {"Employee Name"},
}
];
#[cfg(feature = "test-utils")]
#[test]
fn name_change() {
let ds: emp_table4::Store = sample_emp_table![];
let dv = ds.into_view();
println!("{}", dv);
assert_eq!(dv.nrows(), 7);
assert_eq!(dv.nfields(), 3);
assert_eq!(
dv.fieldnames(),
vec!["Employee Id", "Department Id", "Employee Name"]
);
}
#[cfg(feature = "test-utils")]
#[test]
fn fieldnames() {
let ds = sample_emp_table();
let dv = ds.into_view();
assert_eq!(dv.fieldnames(), vec!["EmpId", "DeptId", "EmpName"]);
}
#[cfg(feature = "test-utils")]
#[test]
fn subview() {
use test_utils::emp_table::*;
let ds = sample_emp_table();
let dv = ds.into_view();
assert_eq!(dv.fieldnames(), vec!["EmpId", "DeptId", "EmpName"]);
assert_eq!(dv.store_ref_counts(), vec![1]);
assert_eq!(dv.nrows(), 7);
assert_eq!(dv.nfields(), 3);
let subdv1 = dv.v::<Labels![EmpId]>();
assert_eq!(subdv1.fieldnames(), vec!["EmpId"]);
assert_eq!(dv.store_ref_counts(), vec![2]);
assert_eq!(subdv1.nrows(), 7);
assert_eq!(subdv1.nfields(), 1);
let subdv1 = dv.v::<Labels![EmpId]>();
assert_eq!(subdv1.fieldnames(), vec!["EmpId"]);
assert_eq!(dv.store_ref_counts(), vec![3]);
assert_eq!(subdv1.nrows(), 7);
assert_eq!(subdv1.nfields(), 1);
let subdv2 = dv.v::<Labels![EmpId, DeptId]>();
assert_eq!(subdv2.fieldnames(), vec!["EmpId", "DeptId"]);
assert_eq!(dv.store_ref_counts(), vec![4]);
assert_eq!(subdv2.nrows(), 7);
assert_eq!(subdv2.nfields(), 2);
let subdv2 = dv.v::<Labels![EmpId, DeptId]>();
assert_eq!(subdv2.fieldnames(), vec!["EmpId", "DeptId"]);
assert_eq!(dv.store_ref_counts(), vec![5]);
assert_eq!(subdv2.nrows(), 7);
assert_eq!(subdv2.nfields(), 2);
let subdv3 = dv.v::<Labels![EmpId, DeptId, EmpName]>();
assert_eq!(subdv3.fieldnames(), vec!["EmpId", "DeptId", "EmpName"]);
assert_eq!(dv.store_ref_counts(), vec![6]);
assert_eq!(subdv3.nrows(), 7);
assert_eq!(subdv3.nfields(), 3);
let subdv3 = dv.v::<Labels![EmpId, DeptId, EmpName]>();
assert_eq!(subdv3.fieldnames(), vec!["EmpId", "DeptId", "EmpName"]);
assert_eq!(dv.store_ref_counts(), vec![7]);
assert_eq!(subdv3.nrows(), 7);
assert_eq!(subdv3.nfields(), 3);
let subdv4 = subdv2.v::<Labels![DeptId]>();
assert_eq!(subdv4.fieldnames(), vec!["DeptId"]);
assert_eq!(dv.store_ref_counts(), vec![8]);
assert_eq!(subdv4.nrows(), 7);
assert_eq!(subdv4.nfields(), 1);
let subdv4 = subdv2.v::<Labels![EmpId]>();
assert_eq!(subdv4.fieldnames(), vec!["EmpId"]);
assert_eq!(dv.store_ref_counts(), vec![9]);
assert_eq!(subdv4.nrows(), 7);
assert_eq!(subdv4.nfields(), 1);
}
#[cfg(feature = "test-utils")]
#[test]
fn subview_merged() {
use test_utils::emp_table::*;
use test_utils::extra_emp::*;
let dv = sample_merged_emp_table();
println!("{:?}", dv.store_ref_counts());
let subdv = dv.v::<Labels![DeptId, DidTraining]>();
println!("{}", subdv);
assert_eq!(subdv.fieldnames(), vec!["DeptId", "DidTraining"]);
assert_eq!(dv.store_ref_counts(), vec![2, 2]);
assert_eq!(subdv.nrows(), 7);
assert_eq!(subdv.nfields(), 2);
}
#[cfg(feature = "test-utils")]
#[test]
fn subview_order() {
use test_utils::emp_table::*;
let dv = sample_emp_table().into_view();
assert_eq!(dv.fieldnames(), vec!["EmpId", "DeptId", "EmpName"]);
let subdv = dv.v::<Labels![DeptId, EmpId]>();
assert_eq!(subdv.fieldnames(), vec!["DeptId", "EmpId"]);
}
#[cfg(feature = "test-utils")]
#[test]
fn sort() {
use test_utils::emp_table::*;
use test_utils::extra_emp::*;
let orig_dv = sample_merged_emp_table();
assert_eq!(orig_dv.nrows(), 7);
let dv1 = orig_dv.clone();
let dv1 = dv1.sort_by_label::<EmpName>();
assert_eq!(
dv1.field::<EmpName>().to_vec(),
vec!["Ann", "Bob", "Cara", "Jamie", "Louis", "Louise", "Sally"]
);
assert_eq!(dv1.field::<EmpId>().to_vec(), vec![10u64, 5, 6, 2, 8, 9, 0]);
let dv2 = dv1.clone();
let dv2 = dv2.sort_by_label::<EmpId>();
assert_eq!(
dv2.field::<EmpName>().to_vec(),
vec!["Sally", "Jamie", "Bob", "Cara", "Louis", "Louise", "Ann"]
);
assert_eq!(dv2.field::<EmpId>().to_vec(), vec![0u64, 2, 5, 6, 8, 9, 10]);
assert_eq!(
dv1.field::<EmpName>().to_vec(),
vec!["Ann", "Bob", "Cara", "Jamie", "Louis", "Louise", "Sally"]
);
assert_eq!(dv1.field::<EmpId>().to_vec(), vec![10u64, 5, 6, 2, 8, 9, 0]);
let dv3 = dv1.clone();
let dv3 = dv3.sort_by_label_comparator::<VacationHrs, _>(
|left: Value<&f32>, right: Value<&f32>| left.partial_cmp(&right).unwrap(),
);
assert_eq!(
dv3.field::<EmpName>().to_vec(),
vec!["Louis", "Louise", "Cara", "Ann", "Sally", "Jamie", "Bob"]
);
assert_eq!(dv3.field::<EmpId>().to_vec(), vec![8u64, 9, 6, 10, 0, 2, 5]);
}
#[cfg(feature = "test-utils")]
#[test]
fn filter() {
use test_utils::emp_table::*;
let orig_dv = sample_emp_table().into_view();
assert_eq!(orig_dv.nrows(), 7);
let dv1 = orig_dv.clone();
let dv1 = dv1.filter::<DeptId, _>(|val: Value<&u64>| val == valref![1]);
println!("{}", dv1);
assert_eq!(dv1.nrows(), 3);
assert_eq!(
dv1.field::<EmpName>().to_vec(),
vec!["Sally", "Bob", "Cara"]
);
let dv1 = dv1.filter::<EmpId, _>(|val: Value<&u64>| val >= valref![6]);
assert_eq!(dv1.nrows(), 1);
assert_eq!(dv1.field::<EmpName>().to_vec(), vec!["Cara"]);
let dv2 = orig_dv.clone();
let dv2 = dv2.filter::<EmpId, _>(|val: Value<&u64>| val >= valref![6]);
assert_eq!(dv2.nrows(), 4);
assert_eq!(
dv2.field::<EmpName>().to_vec(),
vec!["Cara", "Louis", "Louise", "Ann"]
);
let dv2 = dv2.filter::<DeptId, _>(|val: Value<&u64>| val == valref![4]);
assert_eq!(dv2.nrows(), 2);
assert_eq!(dv2.field::<EmpName>().to_vec(), vec!["Louise", "Ann"]);
}
#[cfg(feature = "test-utils")]
#[test]
fn filter_sort() {
use test_utils::emp_table::*;
use test_utils::extra_emp::*;
let orig_dv = sample_merged_emp_table();
assert_eq!(orig_dv.nrows(), 7);
let dv1 = orig_dv.clone();
let dv1 = dv1.filter::<VacationHrs, _>(|val: Value<&f32>| val >= 0.0);
assert_eq!(dv1.nrows(), 6);
assert_eq!(
dv1.field::<EmpName>().to_vec(),
vec!["Sally", "Jamie", "Bob", "Cara", "Louise", "Ann"]
);
let dv2 = dv1.clone();
let dv2 = dv2.sort_by_label::<EmpName>();
assert_eq!(
dv2.field::<EmpName>().to_vec(),
vec!["Ann", "Bob", "Cara", "Jamie", "Louise", "Sally"]
);
let dv3 = dv2.clone();
let dv3 = dv3.filter::<DeptId, _>(|val: Value<&u64>| val == 1);
assert_eq!(dv3.nrows(), 3);
assert_eq!(
dv3.field::<EmpName>().to_vec(),
vec!["Bob", "Cara", "Sally"]
);
assert_eq!(
dv1.field::<EmpName>().to_vec(),
vec!["Sally", "Jamie", "Bob", "Cara", "Louise", "Ann"]
);
let dv1 = dv1.filter::<DeptId, _>(|val: Value<&u64>| val == 1);
assert_eq!(dv1.nrows(), 3);
assert_eq!(
dv1.field::<EmpName>().to_vec(),
vec!["Sally", "Bob", "Cara"]
);
assert_eq!(
dv2.field::<EmpName>().to_vec(),
vec!["Ann", "Bob", "Cara", "Jamie", "Louise", "Sally"]
);
}
#[cfg(feature = "test-utils")]
#[test]
fn unique_single() {
let ds = sample_emp_table();
let dv = ds.into_view();
println!("{}", dv);
let uniques = dv.unique_indices::<Labels![emp_table::DeptId]>();
println!("{:?}", uniques);
assert_eq!(uniques, vec![0, 1, 4, 5]);
let dept_ids = dv.field::<emp_table::DeptId>();
assert_eq![
uniques
.iter()
.map(|&idx| dept_ids.get_datum(idx).unwrap())
.collect::<Vec<_>>(),
vec![1, 2, 3, 4]
];
let unique_deptids = dv.unique_values::<Labels![emp_table::DeptId]>();
println!("{}", unique_deptids);
assert_eq!(
unique_deptids.field::<emp_table::DeptId>().to_vec(),
vec![1, 2, 3, 4]
);
}
#[cfg(feature = "test-utils")]
#[test]
fn unique_composite() {
let dv = sample_merged_emp_table();
let uniq_indices =
dv.unique_indices::<Labels![emp_table::DeptId, extra_emp::DidTraining]>();
assert_eq!(uniq_indices, vec![0, 1, 2, 4, 5, 6]);
let uniq_vals = dv.unique_values::<Labels![emp_table::DeptId, extra_emp::DidTraining]>();
println!("{}", uniq_vals);
assert_eq!(uniq_vals.fieldnames(), vec!["DeptId", "DidTraining",]);
assert_eq!(
uniq_vals.field::<emp_table::DeptId>().to_vec(),
vec![1u64, 2, 1, 3, 4, 4]
);
assert_eq!(
uniq_vals.field::<extra_emp::DidTraining>().to_vec(),
vec![false, false, true, true, false, true]
);
let uniq_vals = dv.unique_values::<Labels![extra_emp::DidTraining, emp_table::DeptId]>();
println!("{}", uniq_vals);
assert_eq!(uniq_vals.fieldnames(), vec!["DidTraining", "DeptId",]);
}
}