Skip to main content

utah2/implement/
impl_constructor_generic.rs

1use super::*;
2use std::string::ToString;
3use std::iter::Iterator;
4use ndarray::Axis;
5
6impl<'a, T> Constructor<'a, T> for DataFrame<T>
7    where T: UtahNum + 'a
8{
9    /// Create a new dataframe. The only required argument is data to populate the dataframe.
10    /// By default, the columns and index of the dataframe are `["1", "2", "3"..."N"]`, where *N* is
11    /// the number of columns (or rows) in the data.
12    ///
13    /// ```
14    /// use utah::prelude::*;
15    /// let a = arr2(&[[2.0, 7.0], [3.0, 4.0]]);
16    /// let df : DataFrame<f64> = DataFrame::new(a);
17    /// ```
18    ///
19    /// When populating the dataframe with mixed-types, wrap the elements with `InnerType` enum:
20    ///
21    /// ```
22    /// use utah::prelude::*;
23    /// let a = arr2(&[[InnerType::Float(2.0), InnerType::Str("ak".into())],
24    ///                [InnerType::Int32(6), InnerType::Int64(10)]]);
25    /// let df : DataFrame<InnerType> = DataFrame::new(a);
26    /// ```
27    fn new<U: Clone>(data: Matrix<U>) -> DataFrame<T>
28        where T: From<U>
29    {
30        let mut data: Matrix<T> = data.mapv(T::from);
31        data.mapv_inplace(|x| {
32            if x.is_empty() {
33                return T::empty();
34            } else {
35                return x;
36            }
37        });
38
39        let columns: Vec<String> = (0..data.shape()[1]).map(|x| x.to_string()).collect();
40
41        let index: Vec<String> = (0..data.shape()[0]).map(|x| x.to_string()).collect();
42
43        DataFrame {
44            data: data,
45            columns: columns,
46            index: index,
47        }
48    }
49    /// Generate a 1-dimensional DataFrame from an 1-D array of data.
50    /// When populating the dataframe with mixed-types, wrap the elements with `InnerType` enum.
51    ///
52    /// ```
53    /// use utah::prelude::*;
54    /// let a = arr1(&[2.0, 7.0]);
55    /// let df : DataFrame<f64> = DataFrame::from_array(a, UtahAxis::Column);
56    /// ```
57    ///
58    fn from_array<U: Clone>(data: Row<U>, axis: UtahAxis) -> DataFrame<T>
59        where T: From<U>
60    {
61        let res_dim = match axis {
62            UtahAxis::Column => (data.len(), 1),
63            UtahAxis::Row => (1, data.len()),
64        };
65        let data: Matrix<T> = data.into_shape(res_dim).unwrap().mapv(T::from);
66        let data: Matrix<T> = data.mapv_into(|x| {
67            if x.is_empty() {
68                return T::empty();
69            } else {
70                return x;
71            }
72        });
73        let columns: Vec<String> = (0..res_dim.1).map(|x| x.to_string()).collect();
74
75        let index: Vec<String> = (0..res_dim.0).map(|x| x.to_string()).collect();
76
77        DataFrame {
78            data: data,
79            columns: columns,
80            index: index,
81        }
82    }
83    /// Populate the dataframe with a set of columns. The column elements can be any of `OuterType`. Example:
84    ///
85    /// ```
86    /// use utah::prelude::*;
87    /// let a = arr2(&[[2.0, 7.0], [3.0, 4.0]]);
88    /// let df : Result<DataFrame<f64>> = DataFrame::new(a).columns(&["a", "b"]);
89    /// df.is_ok();
90    /// ```
91    fn columns<U: Clone>(mut self, columns: &'a [U]) -> Result<DataFrame<T>>
92        where String: From<U>
93    {
94        let data_shape = self.data.shape()[1];
95        let column_shape = columns.len();
96        if column_shape != data_shape {
97            return Err(ErrorKind::ColumnShapeMismatch(data_shape.to_string(),
98                                                      column_shape.to_string())
99                .into());
100        }
101        let new_columns: Vec<String> = columns.iter()
102            .map(|x| x.clone().into())
103            .collect();
104        self.columns = new_columns;
105        Ok(self)
106    }
107
108    /// Populate the dataframe with an index. The index elements can be any of `OuterType`. Example:
109    ///
110    /// ```
111    /// use utah::prelude::*;
112    /// let a = arr2(&[[2.0, 7.0], [3.0, 4.0]]);
113    /// let df : Result<DataFrame<f64>> = DataFrame::new(a).index(&["1", "2"]);
114    /// df.is_ok();
115    /// ```
116    ///
117    /// You can also populate the dataframe with both column names and index names, like so:
118    ///
119    /// ```
120    /// use utah::prelude::*;
121    /// let a = arr2(&[[2.0, 7.0], [3.0, 4.0]]);
122    /// let df : Result<DataFrame<f64>> = DataFrame::new(a).index(&["1", "2"]).unwrap().columns(&["a", "b"]);
123    /// df.is_ok();
124    /// ```
125    fn index<U: Clone>(mut self, index: &'a [U]) -> Result<DataFrame<T>>
126        where String: From<U>
127    {
128        let data_shape = self.data.shape()[0];
129        let index_shape = index.len();
130        if index_shape != data_shape {
131            return Err(ErrorKind::IndexShapeMismatch(data_shape.to_string(),
132                                                     index_shape.to_string())
133                .into());
134        }
135        let new_index: Vec<String> = index.iter()
136            .map(|x| x.clone().into())
137            .collect();
138        self.index = new_index;
139        Ok(self)
140    }
141
142
143    /// Return a dataframe iterator over the specified `UtahAxis`.
144    ///
145    /// The dataframe iterator yields a view of a row or column of the dataframe for eventual
146    /// processing. Example:
147    ///
148    /// ```
149    /// use utah::prelude::*;
150    /// let a = arr2(&[[2.0, 7.0], [3.0, 4.0]]);
151    /// let df : DataFrame<f64> = DataFrame::new(a).index(&["1", "2"]).unwrap().columns(&["a", "b"]).unwrap();
152    /// let df_iter = df.df_iter(UtahAxis::Row);
153    /// ```
154    fn df_iter(&'a self, axis: UtahAxis) -> DataFrameIterator<'a, T> {
155        match axis {
156            UtahAxis::Row => {
157                DataFrameIterator {
158                    names: self.index.iter(),
159                    data: self.data.axis_iter(Axis(0)),
160                    other: self.columns.clone(),
161                    axis: UtahAxis::Row,
162                }
163            }
164            UtahAxis::Column => {
165                DataFrameIterator {
166                    names: self.columns.iter(),
167                    data: self.data.axis_iter(Axis(1)),
168                    other: self.index.to_owned(),
169                    axis: UtahAxis::Column,
170                }
171            }
172        }
173    }
174
175    /// Return a mutable dataframe iterator over the specified `UtahAxis`.
176    ///
177    /// The mutable dataframe iterator yields a view of a row or column of the dataframe for eventual
178    /// processing. Example:
179    ///
180    /// ```
181    /// use utah::prelude::*;
182    /// let a = arr2(&[[2.0, 7.0], [3.0, 4.0]]);
183    /// let mut df : DataFrame<f64> = DataFrame::new(a);
184    /// let df_iter_mut = df.df_iter_mut(UtahAxis::Column);
185    /// ```
186    fn df_iter_mut(&'a mut self, axis: UtahAxis) -> DataFrameMutIterator<'a, T> {
187        match axis {
188            UtahAxis::Row => {
189                DataFrameMutIterator {
190                    names: self.index.iter(),
191                    data: self.data.axis_iter_mut(Axis(0)),
192                    axis: UtahAxis::Row,
193                    other: self.columns.clone(),
194                }
195            }
196            UtahAxis::Column => {
197                DataFrameMutIterator {
198                    names: self.columns.iter(),
199                    data: self.data.axis_iter_mut(Axis(1)),
200                    axis: UtahAxis::Row,
201                    other: self.index.clone(),
202                }
203            }
204        }
205    }
206}