4std::ostream&
operator<<(std::ostream& os,
const std::vector<std::string>& vec) {
7 for (
const auto& elem : vec) {
8 result.append(elem +
", ");
10 result.replace(result.size()-2,2,
"");
15std::ostream&
operator<<(std::ostream& os,
const std::array<int,2>& vec) {
18 for (
const auto& elem : vec) {
19 result.append(std::to_string(elem) +
", ");
21 result.replace(result.size()-2,2,
"");
29 std::cout <<
"Index\t";
32 for (
const auto& colName :
columns) {
33 std::cout << colName <<
"\t";
35 std::cout << std::endl;
37 for (
size_t i = 0; i < nRows; ++i) {
39 std::cout <<
index[i] <<
"\t";
42 for (
const auto& colName :
columns) {
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";
52 std::cout <<
"bug" << std::endl;
55 }
catch (
const std::exception& e) {
56 std::cout << e.what() <<
" " << colName << std::endl;
57 std::cout <<
"ERROR" << std::endl;
61 std::cout << std::endl;
76 n = std::min(n, nRows);
78 for (
const auto& colName :
columns) {
79 const std::type_index& colType = csvOptions.
columnTypes.at(colName);
81 if (colType ==
typeid(
int)) {
83 for (
size_t i = 0; i < n; ++i) {
86 }
else if (colType ==
typeid(
double)) {
88 for (
size_t i = 0; i < n; ++i) {
91 }
else if (colType ==
typeid(std::string)) {
93 for (
size_t i = 0; i < n; ++i) {
101 if (!
index.empty()) {
102 std::vector<std::string> ind(
index.begin(),
index.begin() + n);
111 n = std::min(n, nRows);
113 for (
const auto& colName :
columns) {
114 const std::type_index& colType = csvOptions.
columnTypes.at(colName);
116 if (colType ==
typeid(
int)) {
118 for (
size_t i = nRows - n; i < nRows; ++i)
120 }
else if (colType ==
typeid(
double)) {
122 for (
size_t i = nRows - n; i < nRows; ++i)
124 }
else if (colType ==
typeid(std::string)) {
126 for (
size_t i = nRows - n; i < nRows; ++i)
133 if (!
index.empty()) {
134 std::vector<std::string> ind(
index.end() - n,
index.end());
142 std::cout <<
"Description of numerical columns :" << std::endl;
144 for (
const auto& colName :
columns) {
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);
151 std::cout <<
"Column '" << colName <<
"' is not numerical, then ignored." << std::endl;
157 std::ofstream file(filename);
158 if (!file.is_open())
throw std::runtime_error(
"Could not open file");
165 for (
const auto& c : cols) file <<
"," << c;
168 for (
size_t j = 0; j < cols.size(); ++j) {
170 if (j + 1 < cols.size()) file <<
",";
175 for (
size_t i = 0; i < n; ++i) {
176 if (this->csvOptions.
hasIndex) file << i <<
",";
178 for (
size_t j = 0; j < cols.size(); ++j) {
179 const auto& c = cols[j];
183 throw std::runtime_error(
"Missing type info for column: " + c);
185 const std::type_index& ty = it->second;
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);
194 throw std::runtime_error(
"Unsupported column type for column: " + c);
197 if (j + 1 < cols.size()) file <<
",";
202 std::cout <<
"DataFrame successfully written to " << filename << std::endl;
209 throw std::runtime_error(
"Index is not set");
215 if (newIndex.size() != nRows && nRows > 0) {
216 throw std::invalid_argument(
"Index size does not match number of rows");
220 for (
const auto& colName :
columns) {
223 const std::type_index& t = it->second;
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;
std::ostream & operator<<(std::ostream &os, const std::vector< std::string > &vec)
Stream output helper for a vector of strings.
Minimal tabular container with column-wise storage and CSV I/O.
Simple column-oriented data structure with basic analysis utilities.
void print() const
Prints the DataFrame to std::cout in a tabular format.
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.
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.
const std::vector< std::string > & getColumnNames() const
Returns the list of column names.
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).
std::vector< std::string > columns
List of column names, in insertion order.
void setIndex(const std::vector< std::string > &newIndex)
Sets the index labels for all rows.
Options describing how to interpret or write CSV data.
std::unordered_map< std::string, std::type_index > columnTypes
Mapping from column name to its declared C++ type.
bool hasIndex
True if the CSV representation contains a separate index column.