Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
DataFrame.cpp
Go to the documentation of this file.
1#include "DataFrame.h"
2#include <iostream>
3
4std::ostream& operator<<(std::ostream& os, const std::vector<std::string>& vec) {
5 std::string result{};
6 result.append("[");
7 for (const auto& elem : vec) {
8 result.append(elem + ", ");
9 }
10 result.replace(result.size()-2,2, "");
11 result.append("]");
12 os << result;
13 return os;
14}
15std::ostream& operator<<(std::ostream& os, const std::array<int,2>& vec) {
16 std::string result{};
17 result.append("[");
18 for (const auto& elem : vec) {
19 result.append(std::to_string(elem) + ", ");
20 }
21 result.replace(result.size()-2,2, "");
22 result.append("]");
23 os << result;
24 return os;
25}
26
27void DataFrame::print() const {
28 if (!index.empty()) {
29 std::cout << "Index\t";
30 }
31
32 for (const auto& colName : columns) {
33 std::cout << colName << "\t";
34 }
35 std::cout << std::endl;
36
37 for (size_t i = 0; i < nRows; ++i) {
38 if (!index.empty()) {
39 std::cout << index[i] << "\t";
40 }
41
42 for (const auto& colName : columns) {
43 try {
44
45 if (this->csvOptions.columnTypes.at(colName) == typeid(int)) {
46 std::cout << iat<int>(i, colName) << "\t";
47 } else if (this->csvOptions.columnTypes.at(colName) == typeid(double)) {
48 std::cout << iat<double>(i, colName) << "\t";
49 } else if (this->csvOptions.columnTypes.at(colName) == typeid(std::string)) {
50 std::cout << iat<std::string>(i, colName) << "\t";
51 } else {
52 std::cout << "bug" << std::endl;
53 std::cout << "NaN\t";
54 }
55 } catch (const std::exception& e) {
56 std::cout << e.what() << " " << colName << std::endl;
57 std::cout << "ERROR" << std::endl;
58 std::cout << "NaN\t";
59 }
60 }
61 std::cout << std::endl;
62 }
63}
64
65
66const std::vector<std::string>& DataFrame::getColumnNames() const {
67 return columns;
68}
69
70size_t DataFrame::getRowCount() const {
71 return nRows;
72}
73
74DataFrame DataFrame::head(size_t n) const {
75 DataFrame df;
76 n = std::min(n, nRows);
77
78 for (const auto& colName : columns) {
79 const std::type_index& colType = csvOptions.columnTypes.at(colName);
80
81 if (colType == typeid(int)) {
82 df.addColumn<int>(colName);
83 for (size_t i = 0; i < n; ++i) {
84 df.addValueToColumn<int>(colName, iat<int>(i, colName));
85 }
86 } else if (colType == typeid(double)) {
87 df.addColumn<double>(colName);
88 for (size_t i = 0; i < n; ++i) {
89 df.addValueToColumn<double>(colName, iat<double>(i, colName));
90 }
91 } else if (colType == typeid(std::string)) {
92 df.addColumn<std::string>(colName);
93 for (size_t i = 0; i < n; ++i) {
94 df.addValueToColumn<std::string>(colName, iat<std::string>(i, colName));
95 }
96 }
97 }
98
99 df._set_csv_options(this->csvOptions);
100
101 if (!index.empty()) {
102 std::vector<std::string> ind(index.begin(), index.begin() + n);
103 df.setIndex(ind);
104 }
105
106 return df;
107}
108
109DataFrame DataFrame::tail(size_t n) const {
110 DataFrame df;
111 n = std::min(n, nRows);
112
113 for (const auto& colName : columns) {
114 const std::type_index& colType = csvOptions.columnTypes.at(colName);
115
116 if (colType == typeid(int)) {
117 df.addColumn<int>(colName);
118 for (size_t i = nRows - n; i < nRows; ++i)
119 df.addValueToColumn<int>(colName, iat<int>(i, colName));
120 } else if (colType == typeid(double)) {
121 df.addColumn<double>(colName);
122 for (size_t i = nRows - n; i < nRows; ++i)
123 df.addValueToColumn<double>(colName, iat<double>(i, colName));
124 } else if (colType == typeid(std::string)) {
125 df.addColumn<std::string>(colName);
126 for (size_t i = nRows - n; i < nRows; ++i)
127 df.addValueToColumn<std::string>(colName, iat<std::string>(i, colName));
128 }
129 }
130
131 df._set_csv_options(this->csvOptions);
132
133 if (!index.empty()) {
134 std::vector<std::string> ind(index.end() - n, index.end());
135 df.setIndex(ind);
136 }
137
138 return df;
139}
140
142 std::cout << "Description of numerical columns :" << std::endl;
143
144 for (const auto& colName : columns) {
145
146 if (csvOptions.columnTypes.at(colName) == typeid(int)) {
147 describeColumn<int>(colName);
148 } else if (csvOptions.columnTypes.at(colName) == typeid(double)) {
149 describeColumn<double>(colName);
150 } else {
151 std::cout << "Column '" << colName << "' is not numerical, then ignored." << std::endl;
152 }
153 }
154}
155
156void DataFrame::to_csv(const std::string& filename) {
157 std::ofstream file(filename);
158 if (!file.is_open()) throw std::runtime_error("Could not open file");
159
160 const auto& cols = this->getColumnNames();
161 size_t n = this->getRowCount();
162
163 if (this->csvOptions.hasIndex) {
164 file << "Index";
165 for (const auto& c : cols) file << "," << c;
166 file << "\n";
167 } else {
168 for (size_t j = 0; j < cols.size(); ++j) {
169 file << cols[j];
170 if (j + 1 < cols.size()) file << ",";
171 }
172 file << "\n";
173 }
174
175 for (size_t i = 0; i < n; ++i) {
176 if (this->csvOptions.hasIndex) file << i << ",";
177
178 for (size_t j = 0; j < cols.size(); ++j) {
179 const auto& c = cols[j];
180
181 auto it = this->csvOptions.columnTypes.find(c);
182 if (it == this->csvOptions.columnTypes.end()) {
183 throw std::runtime_error("Missing type info for column: " + c);
184 }
185 const std::type_index& ty = it->second;
186
187 if (ty == typeid(int)) {
188 file << this->iat<int>(i, c);
189 } else if (ty == typeid(double)) {
190 file << this->iat<double>(i, c);
191 } else if (ty == typeid(std::string)) {
192 file << this->iat<std::string>(i, c);
193 } else {
194 throw std::runtime_error("Unsupported column type for column: " + c);
195 }
196
197 if (j + 1 < cols.size()) file << ",";
198 }
199 file << "\n";
200 }
201
202 std::cout << "DataFrame successfully written to " << filename << std::endl;
203}
204
205
206const std::vector<std::string>& DataFrame::getIndex() const {
207
208 if (index.empty()) {
209 throw std::runtime_error("Index is not set");
210 }
211 return index;
212}
213
214void DataFrame::setIndex(const std::vector<std::string>& newIndex) {
215 if (newIndex.size() != nRows && nRows > 0) {
216 throw std::invalid_argument("Index size does not match number of rows");
217 }
218 index = newIndex;
219
220 for (const auto& colName : columns) {
221 auto it = csvOptions.columnTypes.find(colName);
222 if (it == csvOptions.columnTypes.end()) continue;
223 const std::type_index& t = it->second;
224
225 if (t == typeid(int)) {
226 auto s = std::static_pointer_cast<Series<int>>(columns_map.at(colName));
227 *s->getIndex() = index;
228 } else if (t == typeid(double)) {
229 auto s = std::static_pointer_cast<Series<double>>(columns_map.at(colName));
230 *s->getIndex() = index;
231 } else if (t == typeid(std::string)) {
232 auto s = std::static_pointer_cast<Series<std::string>>(columns_map.at(colName));
233 *s->getIndex() = index;
234 }
235 }
236}
237
239 this->csvOptions.hasIndex = options.hasIndex;
240
241 if (!options.columnTypes.empty()) {
242 this->csvOptions.columnTypes = options.columnTypes;
243 }
244 }
std::ostream & operator<<(std::ostream &os, const std::vector< std::string > &vec)
Stream output helper for a vector of strings.
Definition DataFrame.cpp:4
Minimal tabular container with column-wise storage and CSV I/O.
Simple column-oriented data structure with basic analysis utilities.
Definition DataFrame.h:61
void print() const
Prints the DataFrame to std::cout in a tabular format.
Definition DataFrame.cpp:27
DataFrame tail(size_t n=5) const
Returns a new DataFrame with the last n rows.
const std::vector< std::string > & getIndex() const
Returns the current index labels.
void addValueToColumn(const std::string &colName, const T &value)
Appends a value to an existing column.
DataFrame head(size_t n=5) const
Returns a new DataFrame with the first n rows.
Definition DataFrame.cpp:74
void _set_csv_options(const CSVOptions &options)
Internal helper to set CSV options from an external source.
void describe() const
Prints a summary for all numeric columns.
void addColumn(const std::string &colName)
Adds a new empty column of type T.
size_t getRowCount() const
Returns the number of rows in the DataFrame.
Definition DataFrame.cpp:70
const std::vector< std::string > & getColumnNames() const
Returns the list of column names.
Definition DataFrame.cpp:66
void to_csv(const std::string &filename)
Serializes the DataFrame to a CSV file.
std::vector< std::string > index
Optional index labels for the rows (if set).
Definition DataFrame.h:79
std::vector< std::string > columns
List of column names, in insertion order.
Definition DataFrame.h:76
void setIndex(const std::vector< std::string > &newIndex)
Sets the index labels for all rows.
Options describing how to interpret or write CSV data.
Definition CSVOptions.h:31
std::unordered_map< std::string, std::type_index > columnTypes
Mapping from column name to its declared C++ type.
Definition CSVOptions.h:42
bool hasIndex
True if the CSV representation contains a separate index column.
Definition CSVOptions.h:33