bpp-core3  3.0.0
Table.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #ifndef BPP_NUMERIC_TABLE_H
6 #define BPP_NUMERIC_TABLE_H
7 
8 
9 #include "../Clonable.h"
10 #include "TableExceptions.h"
11 #include "VectorTools.h"
12 
13 // From the STL:
14 #include <string>
15 #include <vector>
16 #include <map>
17 #include <memory>
18 
19 
20 namespace bpp
21 {
29 template<class T>
30 class Table :
31  public Clonable
32 {
33 protected:
34  size_t nRow_, nCol_;
35  std::vector< std::vector<T>> data_;
36  std::vector<std::string> rowNames_;
37  std::vector<std::string> colNames_;
38 
39 public:
47  Table(size_t nRow, size_t nCol) :
48  nRow_(nRow),
49  nCol_(nCol),
50  data_(nCol),
51  rowNames_(),
52  colNames_()
53  {
54  for (size_t i = 0; i < nCol; ++i)
55  {
56  data_[i].resize(nRow);
57  }
58  }
59 
67  Table(const std::vector<std::string>& colNames) :
68  nRow_(0),
69  nCol_(colNames.size()),
70  data_(colNames.size()),
71  rowNames_(),
72  colNames_()
73  {
74  setColumnNames(colNames); // May throw an exception.
75  }
76 
77 
78  Table(const Table& table) :
79  nRow_(table.nRow_),
80  nCol_(table.nCol_),
81  data_(table.data_),
82  rowNames_(table.rowNames_),
83  colNames_(table.colNames_)
84  {}
85 
86  Table(const std::vector<std::vector<T>>& vt) :
87  nRow_(vt.size() == 0 ? 0 : vt[0].size()),
88  nCol_(vt.size()),
89  data_(vt),
90  rowNames_(),
91  colNames_()
92  {}
93 
94  Table& operator=(const Table& table)
95  {
96  nRow_ = table.nRow_;
97  nCol_ = table.nCol_;
98  data_ = table.data_;
99  rowNames_ = table.rowNames_;
100  colNames_ = table.colNames_;
101  return *this;
102  }
103 
104  Table& operator=(const std::vector<std::vector<T>>& vt)
105  {
106  nCol_ = vt.size();
107  if (vt.size() == 0)
108  {
109  nRow_ = 0;
110  data_.clear();
111  }
112  else
113  {
114  nRow_ = vt[0].size();
115  data_ = vt;
116  }
117 
118  rowNames_.clear();
119  colNames_.clear();
120  return *this;
121  }
122 
123  Table* clone() const { return new Table(*this); }
124 
125  virtual ~Table() {}
126 
127 public:
132  const std::vector< std::vector<T>>& getData() const
133  {
134  return data_;
135  }
136 
137 
144  T& operator()(size_t rowIndex, size_t colIndex)
145  {
146  if (colIndex >= nCol_)
147  throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", colIndex, 0, nCol_ - 1);
148  if (rowIndex >= data_[colIndex].size())
149  throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", rowIndex, 0, data_[colIndex].size() - 1);
150  return data_[colIndex][rowIndex];
151  }
152 
159  const T& operator()(size_t rowIndex, size_t colIndex) const
160  {
161  if (colIndex >= nCol_)
162  throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", colIndex, 0, nCol_ - 1);
163  if (rowIndex >= data_[colIndex].size())
164  throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", rowIndex, 0, data_[colIndex].size() - 1);
165  return data_[colIndex][rowIndex];
166  }
167 
176  T& operator()(const std::string& rowName, const std::string& colName)
177  {
178  if (rowNames_.size() == 0)
179  throw NoTableRowNamesException("Table::operator(const string &, const string &).");
180  if (colNames_.size() == 0)
181  throw NoTableColumnNamesException("Table::operator(const string &, const string &).");
182  try
183  {
184  size_t rowIndex = VectorTools::which(rowNames_, rowName);
185  size_t colIndex = VectorTools::which(colNames_, colName);
186  return (*this)(rowIndex, colIndex);
187  }
189  {
190  throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
191  }
192  }
193 
203  const T& operator()(const std::string& rowName, const std::string& colName) const
204  {
205  if (rowNames_.size() == 0)
206  throw NoTableRowNamesException("Table::operator(const string &, const string &).");
207  if (colNames_.size() == 0)
208  throw NoTableColumnNamesException("Table::operator(const string &, const string &).");
209  try
210  {
211  size_t rowIndex = VectorTools::which(rowNames_, rowName);
212  size_t colIndex = VectorTools::which(colNames_, colName);
213  return (*this)(rowIndex, colIndex);
214  }
216  {
217  throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
218  }
219  }
220 
221 
230  T& operator()(const std::string& rowName, size_t colIndex)
231  {
232  if (rowNames_.size() == 0)
233  throw NoTableRowNamesException("Table::operator(const string &, size_t).");
234  if (colIndex >= nCol_)
235  throw IndexOutOfBoundsException("Table::operator(const string &, size_t).", colIndex, 0, nCol_ - 1);
236  try
237  {
238  size_t rowIndex = VectorTools::which(rowNames_, rowName);
239  return (*this)(rowIndex, colIndex);
240  }
242  {
243  throw TableNameNotFoundException("Table::operator(const string &, size_t).", *ex.getElement());
244  }
245  }
246 
247 
256  const T& operator()(const std::string& rowName, size_t colIndex) const
257  {
258  if (rowNames_.size() == 0)
259  throw NoTableRowNamesException("Table::operator(const string &, size_t).");
260  if (colIndex >= nCol_)
261  throw IndexOutOfBoundsException("Table::operator(const string &, size_t).", colIndex, 0, nCol_ - 1);
262  try
263  {
264  size_t rowIndex = VectorTools::which(rowNames_, rowName);
265  return (*this)(rowIndex, colIndex);
266  }
268  {
269  throw TableNameNotFoundException("Table::operator(const string &, size_t).", *ex.getElement());
270  }
271  }
272 
273 
282  T& operator()(size_t rowIndex, const std::string& colName)
283  {
284  if (colNames_.size() == 0)
285  throw NoTableColumnNamesException("Table::operator(size_t, const string &).");
286  try
287  {
288  size_t colIndex = VectorTools::which(colNames_, colName);
289  if (rowIndex >= data_[colIndex].size())
290  throw IndexOutOfBoundsException("Table::operator(size_t, const string &).", rowIndex, 0, data_[colIndex].size() - 1);
291  return (*this)(rowIndex, colIndex);
292  }
294  {
295  throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
296  }
297  }
298 
299 
308  const T& operator()(size_t rowIndex, const std::string& colName) const
309  {
310  if (colNames_.size() == 0)
311  throw NoTableColumnNamesException("Table::operator(size_t, const string &).");
312  try
313  {
314  size_t colIndex = VectorTools::which(colNames_, colName);
315  if (rowIndex >= data_[colIndex].size())
316  throw IndexOutOfBoundsException("Table::operator(size_t, const string &).", rowIndex, 0, data_[colIndex].size() - 1);
317  return (*this)(rowIndex, colIndex);
318  }
320  {
321  throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
322  }
323  }
324 
334  size_t getNumberOfColumns() const { return nCol_; }
335 
343  void setColumnNames(const std::vector<std::string>& colNames)
344  {
345  if (!VectorTools::isUnique(colNames))
346  throw DuplicatedTableColumnNameException("Table::setColumnNames(...). Column names must be unique.");
347  if (colNames.size() != nCol_)
348  throw DimensionException("Table::setColumnNames.", colNames.size(), nCol_);
349  else
350 
351  colNames_ = colNames;
352  }
353 
360  const std::vector<std::string>& getColumnNames() const
361  {
362  if (colNames_.size() == 0)
363  throw NoTableColumnNamesException("Table::getColumnNames().");
364  return colNames_;
365  }
366 
367  std::vector<std::string>& getColumnNames()
368  {
369  if (colNames_.size() == 0)
370  throw NoTableColumnNamesException("Table::getColumnNames().");
371  return colNames_;
372  }
373 
382  std::string getColumnName(size_t index) const
383  {
384  if (colNames_.size() == 0)
385  throw NoTableColumnNamesException("Table::getColumnName(size_t).");
386  if (index >= nCol_)
387  throw IndexOutOfBoundsException("Table::getColumnName(size_t).", index, 0, nCol_ - 1);
388  return colNames_[index];
389  }
390 
391 
395  bool hasColumnNames() const { return colNames_.size() != 0; }
396 
402  std::vector<T>& getColumn(size_t index)
403  {
404  if (index >= nCol_)
405  throw IndexOutOfBoundsException("Table::getColumn(size_t).", index, 0, nCol_ - 1);
406  return data_[index];
407  }
408 
414  const std::vector<T>& getColumn(size_t index) const
415  {
416  if (index >= nCol_)
417  throw IndexOutOfBoundsException("Table::getColumn(size_t).", index, 0, nCol_ - 1);
418  return data_[index];
419  }
420 
421 
428  std::vector<T>& getColumn(const std::string& colName)
429  {
430  if (colNames_.size() == 0)
431  throw NoTableColumnNamesException("Table::getColumn(const string &).");
432  try
433  {
434  size_t colIndex = VectorTools::which(colNames_, colName);
435  return data_[colIndex];
436  }
438  {
439  throw TableColumnNameNotFoundException("Table::getColumn(const string &).", colName);
440  }
441  }
442 
449  const std::vector<T>& getColumn(const std::string& colName) const
450  {
451  if (colNames_.size() == 0)
452  throw NoTableColumnNamesException("Table::getColumn(const string &).");
453  try
454  {
455  size_t colIndex = VectorTools::which(colNames_, colName);
456  return data_[colIndex];
457  }
459  {
460  throw TableColumnNameNotFoundException("Table::getColumn(const string &).", colName);
461  }
462  }
463 
464 
471  bool hasColumn(const std::string& colName) const
472  {
473  if (colNames_.size() == 0)
474  return false;
475  for (size_t i = 0; i < colNames_.size(); i++)
476  {
477  if ((colNames_)[i] == colName)
478  return true;
479  }
480  return false;
481  }
482 
483 
490  void deleteColumn(size_t index)
491  {
492  if (index >= nCol_)
493  throw IndexOutOfBoundsException("Table::deleteColumn(size_t).", index, 0, nCol_ - 1);
494  data_.erase(data_.begin() + (long)index);
495  if (colNames_.size() != 0)
496  colNames_.erase(colNames_.begin() + (long)(index));
497  nCol_--;
498  }
499 
507  void deleteColumns(size_t index, size_t len)
508  {
509  if (index >= nCol_)
510  throw IndexOutOfBoundsException("Table::deleteColumns(size_t, size_t).", index, 0, nCol_ - 1);
511  if (index + len >= nCol_)
512  throw IndexOutOfBoundsException("Table::deleteColumns(size_t, size_t).", index + len, 0, nCol_ - 1);
513 
514  data_.erase(data_.begin() + (long)index, data_.begin() + (long)(index + len));
515  if (colNames_.size() != 0)
516  colNames_.erase(colNames_.begin() + (long)(index), colNames_.begin() + (long)(index + len));
517 
518  nCol_ -= len;
519  }
520 
528  void deleteColumn(const std::string& colName)
529  {
530  if ((colNames_.size() == 0))
531  throw NoTableColumnNamesException("Table::deleteColumn(const string &).");
532  try
533  {
534  size_t colIndex = VectorTools::which(colNames_, colName);
535  data_.erase(data_.begin() + (size_t)(colIndex));
536  colNames_.erase(colNames_.begin() + (size_t)(colIndex));
537  nCol_--;
538  }
540  {
541  throw TableColumnNameNotFoundException("Table::deleteColumn(const string &).", colName);
542  }
543  }
544 
545 
554  void addColumn(const std::vector<T>& newColumn, int pos = -1)
555  {
556  if (pos > (int)nCol_)
557  throw DimensionException("Table::addColumn.", (size_t)pos, nCol_);
558  if (pos == -1)
559  pos = (int)nCol_;
560 
561  if (colNames_.size())
562  throw TableColumnNamesException("Table::addColumn. Table has column names.");
563  if (newColumn.size() != nRow_)
564  throw DimensionException("Table::addColumn.", newColumn.size(), nRow_);
565 
566  data_.insert(data_.begin() + pos, newColumn);
567  nCol_++;
568  }
569 
580  void addColumn(const std::string& colName, const std::vector<T>& newColumn, int pos = -1)
581  {
582  if (pos > (int)nCol_)
583  throw DimensionException("Table::addColumn.", pos, nCol_);
584  if (pos == -1)
585  pos = nCol_;
586 
587  if ((colNames_.size() == 0) && (nCol_ != 0))
588  throw NoTableColumnNamesException("Table::addColumn. Table has column names.");
589 
590  if (newColumn.size() != nRow_)
591  throw DimensionException("Table::addColumn.", newColumn.size(), nRow_);
592  if (nCol_ > 0 && find(colNames_.begin(), colNames_.end(), colName) != colNames_.end())
593  throw DuplicatedTableColumnNameException("Table::addColumn(const string &, const std::vector<string> &). Column names must be unique.");
594 
595  colNames_.insert(colNames_.begin() + pos, colName);
596  data_.insert(data_.begin() + pos, newColumn);
597  nCol_++;
598  }
599 
609  void addColumn(std::string& st, const std::string& sep = "\t", int pos = -1, int rowCol = -1)
610  {
611  if (pos > (int)nCol_)
612  throw DimensionException("Table::addColumn.", (size_t)pos, nCol_);
613  if (pos == -1)
614  pos = (int)nCol_;
615 
616  StringTokenizer stok(st, sep, false, true);
617  std::vector<std::string> row(stok.getTokens().begin(), stok.getTokens().end());
618 
619  if (row.size() != nRow_ + (rowCol >= 0) ? 1 : 0)
620  throw BadIntegerException("Table::addColumn. Bad number of rows: ", (int)row.size());
621 
622  std::vector<T> newColumn;
623 
624  for (size_t i = 0; i < row.size(); i++)
625  {
626  if ((int)i == rowCol)
627  {
628  std::string colName = row[i];
629  if (find(colNames_.begin(), colNames_.end(), colName) != colNames_.end())
630  throw DuplicatedTableColumnNameException("Table::addColumn(const std::vector<string> &). Column names must be unique.");
631 
632  colNames_.insert(colNames_.begin() + (long)pos, colName);
633  }
634  else
635  {
636  std::stringstream ss(row[i]);
637  T t;
638  ss >> t;
639  newColumn.push_back(t);
640  }
641  }
642  data_.insert(data_.begin() + pos, newColumn);
643 
644  nCol_++;
645  }
646 
647 
656  void setColumn(const std::vector<T>& newColumn, size_t pos)
657  {
658  if (pos >= nCol_)
659  throw DimensionException("Table::setColumn.", pos, nCol_);
660 
661  if (newColumn.size() != nRow_)
662  throw DimensionException("Table::setColumn.", newColumn.size(), nRow_);
663 
664  data_[pos] = newColumn;
665  }
666 
677  void setColumn(const std::string& colName, const std::vector<T>& newColumn, size_t pos)
678  {
679  if (pos >= nCol_)
680  throw DimensionException("Table::setColumn.", pos, nCol_);
681 
682  if (colNames_.size() == 0)
683  throw NoTableColumnNamesException("Table::setColumn. Table has column names.");
684 
685  if (newColumn.size() != nRow_)
686  throw DimensionException("Table::setColumn.", newColumn.size(), nRow_);
687 
688  if (find(colNames_.begin(), colNames_.end(), colName) != colNames_.end() &&
689  find(colNames_.begin(), colNames_.end(), colName) != colNames_.begin() + pos)
690  throw DuplicatedTableColumnNameException("Table::setColumn(const string &, const std::vector<T> &, size_t). Column names must be unique.");
691 
692  colNames_[pos] = colName;
693  data_[pos] = newColumn;
694  }
695 
707  size_t getNumberOfRows() const { return nRow_; }
708 
716  void setRowNames(const std::vector<std::string>& rowNames)
717  {
718  if (!VectorTools::isUnique(rowNames))
719  {
720  throw DuplicatedTableRowNameException("Table::setRowNames(...). Row names must be unique.");
721  }
722  if (rowNames.size() != nRow_)
723  throw DimensionException("Table::setRowNames.", rowNames.size(), nRow_);
724  else
725  {
726  rowNames_ = rowNames;
727  }
728  }
729 
730 
737  std::vector<std::string> getRowNames()
738  {
739  if (rowNames_.size() == 0)
740  throw NoTableRowNamesException("Table::getRowNames().");
741  return rowNames_;
742  }
743 
744  const std::vector<std::string>& getRowNames() const
745  {
746  if (rowNames_.size() == 0)
747  throw NoTableRowNamesException("Table::getRowNames().");
748  return rowNames_;
749  }
750 
751 
758  bool hasRow(const std::string& rowName) const
759  {
760  if (rowNames_.size() == 0)
761  return false;
762  for (size_t i = 0; i < rowNames_.size(); i++)
763  {
764  if ((rowNames_)[i] == rowName)
765  return true;
766  }
767  return false;
768  }
769 
770 
779  std::string getRowName(size_t index) const
780  {
781  if (rowNames_.size() == 0)
782  throw NoTableRowNamesException("Table::getRowName(size_t).");
783  if (index >= nRow_)
784  throw IndexOutOfBoundsException("Table::getRowName(size_t).", index, 0, nRow_ - 1);
785  return (rowNames_)[index];
786  }
787 
788 
792  bool hasRowNames() const { return rowNames_.size() != 0; }
793 
799  std::vector<T> getRow(size_t index) const
800  {
801  if (index >= nRow_)
802  throw IndexOutOfBoundsException("Table::getRow(size_t).", index, 0, nRow_ - 1);
803  std::vector<T> row;
804  for (size_t i = 0; i < nCol_; i++)
805  {
806  row.push_back(data_[i][index]);
807  }
808  return row;
809  }
810 
811 
818  std::vector<T> getRow(const std::string& rowName) const
819  {
820  if ((rowNames_.size() == 0))
821  throw NoTableRowNamesException("Table::getRow(const string &).");
822  try
823  {
824  size_t rowIndex = VectorTools::which(rowNames_, rowName);
825  std::vector<T> row;
826  for (size_t i = 0; i < nCol_; i++)
827  {
828  row.push_back(data_[i][rowIndex]);
829  }
830  return row;
831  }
833  {
834  throw TableRowNameNotFoundException("Table::getRow(const string &).", rowName);
835  }
836  }
837 
838 
845  void deleteRow(size_t index)
846  {
847  for (size_t j = 0; j < nCol_; j++)
848  {
849  std::vector<T>* column = &data_[j];
850  if (index >= column->size())
851  throw IndexOutOfBoundsException("Table::deleteRow(size_t).", index, 0, column->size() - 1);
852  column->erase(column->begin() + index);
853  }
854  if (rowNames_.size() != 0)
855  rowNames_.erase(rowNames_.begin() + index);
856  nRow_--;
857  }
858 
866  void deleteRows(size_t index, size_t len)
867  {
868  for (size_t j = 0; j < nCol_; j++)
869  {
870  std::vector<T>* column = &data_[j];
871  if (index >= column->size())
872  throw IndexOutOfBoundsException("Table::deleteRow(size_t).", index, 0, column->size() - 1);
873  column->erase(column->begin() + (long)index, column->begin() + long(index + len));
874  }
875  if (rowNames_.size() != 0)
876  rowNames_.erase(rowNames_.begin() + long(index), rowNames_.begin() + long(index + len));
877  nRow_--;
878  }
879 
880 
888  void deleteRow(const std::string& rowName)
889  {
890  if ((rowNames_.size() == 0))
891  throw NoTableRowNamesException("Table::deleteRow(const string &).");
892  try
893  {
894  size_t rowIndex = VectorTools::which(rowNames_, rowName);
895  for (size_t j = 0; j < nCol_; j++)
896  {
897  std::vector<T>* column = &data_[j];
898  column->erase(column->begin() + rowIndex);
899  }
900  rowNames_.erase(rowNames_.begin() + rowIndex);
901  nRow_--;
902  }
904  {
905  throw TableRowNameNotFoundException("Table::deleteRow(const string &).", rowName);
906  }
907  }
908 
909 
916  void addRow(const std::vector<T>& newRow, int pos = -1)
917  {
918  if (pos > (int)nRow_)
919  throw DimensionException("Table::addRow.", pos, nRow_);
920 
921  if (pos == -1)
922  pos = nRow_;
923 
924  if (rowNames_.size() != 0)
925  throw TableRowNamesException("Table::addRow. Table has row names.");
926  if (newRow.size() != nCol_)
927  throw DimensionException("Table::addRow.", newRow.size(), nCol_);
928  for (size_t j = 0; j < nCol_; j++)
929  {
930  data_[j].insert(data_[j].begin() + (size_t)pos, newRow[j]);
931  }
932  nRow_++;
933  }
934 
942  void addRow(const std::string& rowName, const std::vector<T>& newRow, int pos = -1)
943  {
944  if (pos > (int)nRow_)
945  throw DimensionException("Table::addRow.", pos, nRow_);
946  if (pos == -1)
947  pos = nRow_;
948 
949  if ((rowNames_.size() == 0) && (nRow_ != 0))
950  throw NoTableRowNamesException("Table::addRow. Table has row names.");
951 
952  if (newRow.size() != nCol_)
953  throw DimensionException("Table::addRow.", newRow.size(), nCol_);
954  if (nRow_ > 0 && find(rowNames_.begin(), rowNames_.end(), rowName) != rowNames_.end())
955  throw DuplicatedTableRowNameException("Table::addRow(const string &, const std::vector<string> &). Row names must be unique.");
956  rowNames_.insert(rowNames_.begin() + (size_t)pos, rowName);
957  for (size_t j = 0; j < nCol_; j++)
958  {
959  data_[j].insert(data_[j].begin() + (size_t)pos, newRow[j]);
960  }
961  nRow_++;
962  }
963 
973  void addRow(std::string& st, const std::string& sep = "\t", int pos = -1, int rowCol = -1)
974  {
975  if (pos > (int)nRow_)
976  throw DimensionException("Table::addRow.", (size_t)pos, nRow_);
977  if (pos == -1)
978  pos = (int)nRow_;
979 
980  StringTokenizer stok(st, sep, false, true);
981  std::vector<std::string> row(stok.getTokens().begin(), stok.getTokens().end());
982 
983  if (row.size() != nCol_ + (rowCol >= 0) ? 1 : 0)
984  throw BadIntegerException("Table::addRow. Bad number of columns: ", (int)row.size());
985 
986  size_t id = 0;
987 
988  for (size_t i = 0; i < row.size(); i++)
989  {
990  if ((int)i == rowCol)
991  {
992  std::string rowName = row[i];
993  if (find(rowNames_.begin(), rowNames_.end(), rowName) != rowNames_.end())
994  throw DuplicatedTableRowNameException("Table::addRow(const std::vector<string> &). Row names must be unique.");
995 
996  rowNames_.insert(rowNames_.begin() + (long)pos, rowName);
997  }
998  else
999  {
1000  std::stringstream ss(row[i]);
1001  T t;
1002  ss >> t;
1003  data_[id].insert(data_[id].begin() + (long)pos, t);
1004  id++;
1005  }
1006  }
1007  nRow_++;
1008  }
1009 
1010 
1013 public:
1031  static std::unique_ptr<Table<T>> read(std::istream& in, bool byRow, const std::string& sep = "\t", bool header = true, int names = -1)
1032  {
1033  std::string firstLine = FileTools::getNextLine(in);
1034  StringTokenizer st1(firstLine, sep, false, true);
1035  std::vector<std::string> row1(st1.getTokens().begin(), st1.getTokens().end());
1036  size_t nCol = row1.size();
1037  std::unique_ptr< Table<T>> dt;
1038 
1039  if (header)
1040  {
1041  // Use first line as header.
1042  if (byRow)
1043  {
1044  dt = std::make_unique<Table<T>>(0, nCol);
1045  dt->setColumnNames(row1);
1046  }
1047  else
1048  {
1049  dt = std::make_unique<Table<T>>(nCol, 0);
1050  dt->setRowNames(row1);
1051  }
1052  }
1053  else
1054  {
1055  if (byRow)
1056  {
1057  dt = std::make_unique<Table<T>>(0, nCol - (names >= 0 ? 1 : 0));
1058  dt->addRow(firstLine, sep, names);
1059  }
1060  else
1061  {
1062  dt = std::make_unique<Table<T>>(nCol - (names >= 0 ? 1 : 0), 0);
1063  dt->addColumn(firstLine, sep, names);
1064  }
1065  }
1066 
1067  // Now read each line:
1068  std::string line = FileTools::getNextLine(in);
1069 
1070  while (!TextTools::isEmpty(line))
1071  {
1072  if (byRow)
1073  dt->addRow(line, sep, names);
1074  else
1075  dt->addColumn(line, sep, names);
1076 
1077  line = FileTools::getNextLine(in);
1078  }
1079  return dt;
1080  }
1081 
1082 
1092  static void write(const Table& data, std::ostream& out, bool byRow, const std::string& sep = "\t", bool alignHeaders = false)
1093  {
1094  size_t n = (byRow ? data.getNumberOfColumns() : data.getNumberOfRows());
1095  if (n == 0)
1096  return;
1097  size_t m = (byRow ? data.getNumberOfRows() : data.getNumberOfColumns());
1098 
1099  bool frontNames = ((byRow && data.hasRowNames()) || (!byRow && data.hasColumnNames()));
1100 
1101  if ((byRow && data.hasColumnNames()) || (!byRow && data.hasRowNames()))
1102  { // Write header
1103  std::vector<std::string> names = (byRow ? data.getColumnNames() : data.getRowNames());
1104 
1105  if (alignHeaders && frontNames)
1106  out << sep;
1107  out << names[0];
1108  for (size_t i = 1; i < n; ++i)
1109  {
1110  out << sep << names[i];
1111  }
1112  out << std::endl;
1113  }
1114 
1115  // now write each row (or column):
1116 
1117  for (size_t i = 0; i < m; ++i)
1118  {
1119  if (frontNames)
1120  {
1121  out << (byRow ? data.getRowName(i) : data.getColumnName(i)) << sep;
1122  }
1123 
1124  out << (byRow ? data(i, 0) : data(0, i));
1125  for (size_t j = 1; j < n; ++j)
1126  {
1127  out << sep << (byRow ? data(i, j) : data(j, i));
1128  }
1129  out << std::endl;
1130  }
1131  }
1132 
1133  static void write(const Table& data, bpp::OutputStream& out, bool byRow, const std::string& sep = "\t", bool alignHeaders = false)
1134  {
1135  size_t n = (byRow ? data.getNumberOfColumns() : data.getNumberOfRows());
1136  if (n == 0)
1137  return;
1138  size_t m = (byRow ? data.getNumberOfRows() : data.getNumberOfColumns());
1139 
1140  bool frontNames = ((byRow && data.hasRowNames()) || (!byRow && data.hasColumnNames()));
1141 
1142  if ((byRow && data.hasColumnNames()) || (!byRow && data.hasRowNames()))
1143  { // Write header
1144  std::vector<std::string> names = (byRow ? data.getColumnNames() : data.getRowNames());
1145 
1146  if (alignHeaders && frontNames)
1147  out << sep;
1148  out << names[0];
1149  for (size_t i = 1; i < n; ++i)
1150  {
1151  out << sep << names[i];
1152  }
1153  out.endLine();
1154  }
1155 
1156  // now write each row (or column):
1157 
1158  for (size_t i = 0; i < m; ++i)
1159  {
1160  if (frontNames)
1161  out << (byRow ? data.getRowName(i) : data.getColumnName(i)) << sep;
1162 
1163  out << (byRow ? data(i, 0) : data(0, i));
1164  for (size_t j = 1; j < n; ++j)
1165  {
1166  out << sep << (byRow ? data(i, j) : data(j, i));
1167  }
1168  out.endLine();
1169  }
1170  }
1171 };
1172 } // end of namespace bpp.
1173 #endif // BPP_NUMERIC_TABLE_H
size_t getNumberOfColumns() const
Definition: Table.h:334
Table(const std::vector< std::string > &colNames)
Build a new void Table object with named columns.
Definition: Table.h:67
void deleteRows(size_t index, size_t len)
Delete the given rows.
Definition: Table.h:866
void addRow(std::string &st, const std::string &sep="\, int pos=-1, int rowCol=-1)
Add a new row.
Definition: Table.h:973
size_t getNumberOfRows() const
Definition: Table.h:707
std::vector< T > getRow(const std::string &rowName) const
Definition: Table.h:818
virtual ~Table()
Definition: Table.h:125
void addRow(const std::vector< T > &newRow, int pos=-1)
Add a new row.
Definition: Table.h:916
const T & operator()(size_t rowIndex, size_t colIndex) const
Definition: Table.h:159
A tokenizer for strings.
const std::vector< std::string > & getRowNames() const
Definition: Table.h:744
std::string getRowName(size_t index) const
Get a given row name.
Definition: Table.h:779
void deleteRow(size_t index)
Delete the given row.
Definition: Table.h:845
T & operator()(size_t rowIndex, const std::string &colName)
Definition: Table.h:282
size_t nRow_
Definition: Table.h:34
T & operator()(const std::string &rowName, const std::string &colName)
Definition: Table.h:176
std::vector< T > & getColumn(size_t index)
Definition: Table.h:402
Table & operator=(const std::vector< std::vector< T >> &vt)
Definition: Table.h:104
Number exception: integers.
Definition: Exceptions.h:77
const T & operator()(size_t rowIndex, const std::string &colName) const
Definition: Table.h:308
void setColumn(const std::vector< T > &newColumn, size_t pos)
Set a new column.
Definition: Table.h:656
T & operator()(size_t rowIndex, size_t colIndex)
Definition: Table.h:144
Exception thrown when a given column name is not found is a DataTable object.
static void write(const Table &data, std::ostream &out, bool byRow, const std::string &sep="\, bool alignHeaders=false)
Write a Table object to stream in CSV-like format.
Definition: Table.h:1092
Exception thrown when attempting to duplicate a row name.
const T & operator()(const std::string &rowName, size_t colIndex) const
Definition: Table.h:256
Exception thrown when trying to retrieve a row by its name and no row names have been specified...
void addColumn(const std::vector< T > &newColumn, int pos=-1)
Add a new column.
Definition: Table.h:554
Exception thrown when a given element was not found in the vector.
const T & operator()(const std::string &rowName, const std::string &colName) const
Definition: Table.h:203
Table * clone() const
Create a copy of this object and send a pointer to it.
Definition: Table.h:123
const std::vector< T > & getColumn(size_t index) const
Definition: Table.h:414
static void write(const Table &data, bpp::OutputStream &out, bool byRow, const std::string &sep="\, bool alignHeaders=false)
Definition: Table.h:1133
size_t nCol_
Definition: Table.h:34
void deleteColumn(const std::string &colName)
Delete the given column.
Definition: Table.h:528
void deleteColumn(size_t index)
Delete the given column.
Definition: Table.h:490
static size_t which(const std::vector< T > &v, const T &which)
Send the position of the first occurence of &#39;which&#39;.
Definition: VectorTools.h:402
void setColumn(const std::string &colName, const std::vector< T > &newColumn, size_t pos)
Set a new column.
Definition: Table.h:677
std::vector< T > getRow(size_t index) const
Definition: Table.h:799
bool hasColumn(const std::string &colName) const
Tell is a given column exists.
Definition: Table.h:471
void addColumn(const std::string &colName, const std::vector< T > &newColumn, int pos=-1)
Add a new column.
Definition: Table.h:580
Exception thrown when a given row name is not found is a DataTable object.
const std::vector< std::vector< T > > & getData() const
Definition: Table.h:132
Table(const std::vector< std::vector< T >> &vt)
Definition: Table.h:86
std::vector< std::vector< T > > data_
Definition: Table.h:35
void deleteColumns(size_t index, size_t len)
Delete the given columns.
Definition: Table.h:507
std::vector< T > & getColumn(const std::string &colName)
Definition: Table.h:428
Excpetion thrown when attempting to duplicate a column name.
Exception thrown when trying to retrieve a column by its name and no column names have been specified...
static std::string getNextLine(std::istream &in)
Get the next non-blanck line of a stream.
Definition: FileTools.cpp:108
bool hasRow(const std::string &rowName) const
Tell is a given row exists.
Definition: Table.h:758
const std::deque< std::string > & getTokens() const
Retrieve all tokens.
std::vector< std::string > colNames_
Definition: Table.h:37
const std::vector< T > & getColumn(const std::string &colName) const
Definition: Table.h:449
virtual OutputStream & endLine()=0
OutputStream interface.
Definition: OutputStream.h:29
void setRowNames(const std::vector< std::string > &rowNames)
Set the row names of this table.
Definition: Table.h:716
void addRow(const std::string &rowName, const std::vector< T > &newRow, int pos=-1)
Add a new row at a given position.
Definition: Table.h:942
Table(size_t nRow, size_t nCol)
Build a new void Table object with nRow rows and nCol columns.
Definition: Table.h:47
std::vector< std::string > & getColumnNames()
Definition: Table.h:367
bool hasRowNames() const
Definition: Table.h:792
The Clonable interface (allow an object to be cloned).
Definition: Clonable.h:63
static bool isUnique(const std::vector< T > &v)
Tell if the std::vector as unique elements.
Definition: VectorTools.h:471
std::vector< std::string > getRowNames()
Get the row names of this table.
Definition: Table.h:737
const std::vector< std::string > & getColumnNames() const
Get the column names of this table.
Definition: Table.h:360
T & operator()(const std::string &rowName, size_t colIndex)
Definition: Table.h:230
std::string getColumnName(size_t index) const
Get a given column name.
Definition: Table.h:382
This class corresponds to a &#39;dataset&#39;, i.e. a table with data by rows and variable by columns...
Definition: Table.h:30
Index out of bounds exception class.
Definition: Exceptions.h:131
Exception thrown when a given name is not found is a DataTable object.
void addColumn(std::string &st, const std::string &sep="\, int pos=-1, int rowCol=-1)
Add a new column.
Definition: Table.h:609
bool isEmpty(const std::string &s)
Tell if a string is empty. A string is considered to be &#39;empty&#39; if it is only made of white spaces...
Definition: TextTools.cpp:20
void setColumnNames(const std::vector< std::string > &colNames)
Set the column names of this table.
Definition: Table.h:343
bool hasColumnNames() const
Definition: Table.h:395
Table & operator=(const Table &table)
Definition: Table.h:94
Table(const Table &table)
Definition: Table.h:78
static std::unique_ptr< Table< T > > read(std::istream &in, bool byRow, const std::string &sep="\, bool header=true, int names=-1)
Read a table form a stream in CSV-like.
Definition: Table.h:1031
Exception thrown when a dimension problem occured.
General exception class dealing with column names.
void deleteRow(const std::string &rowName)
Delete the given row.
Definition: Table.h:888
General exception class dealing with row names.
std::vector< std::string > rowNames_
Definition: Table.h:36