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}