bpp-core3  3.0.0
Table.h
Go to the documentation of this file.
1 //
2 // File: Table.h
3 // Authors:
4 // Laurent Guéguen
5 // Created: dimanche 2 avril 2017, à 22h 59
6 //
7 
8 /*
9  Copyright or © or Copr. Bio++ Development Team, (November 17, 2004)
10 
11  This software is a computer program whose purpose is to provide classes
12  for numerical calculus.
13 
14  This software is governed by the CeCILL license under French law and
15  abiding by the rules of distribution of free software. You can use,
16  modify and/ or redistribute the software under the terms of the CeCILL
17  license as circulated by CEA, CNRS and INRIA at the following URL
18  "http://www.cecill.info".
19 
20  As a counterpart to the access to the source code and rights to copy,
21  modify and redistribute granted by the license, users are provided only
22  with a limited warranty and the software's author, the holder of the
23  economic rights, and the successive licensors have only limited
24  liability.
25 
26  In this respect, the user's attention is drawn to the risks associated
27  with loading, using, modifying and/or developing or reproducing the
28  software by the user in light of its specific status of free software,
29  that may mean that it is complicated to manipulate, and that also
30  therefore means that it is reserved for developers and experienced
31  professionals having in-depth computer knowledge. Users are therefore
32  encouraged to load and test the software's suitability as regards their
33  requirements in conditions enabling the security of their systems and/or
34  data to be ensured and, more generally, to use and operate it in the
35  same conditions as regards security.
36 
37  The fact that you are presently reading this means that you have had
38  knowledge of the CeCILL license and that you accept its terms.
39 */
40 
41 #ifndef BPP_NUMERIC_TABLE_H
42 #define BPP_NUMERIC_TABLE_H
43 
44 
45 #include "../Clonable.h"
46 #include "TableExceptions.h"
47 #include "VectorTools.h"
48 
49 // From the STL:
50 #include <string>
51 #include <vector>
52 #include <map>
53 #include <memory>
54 
55 
56 namespace bpp
57 {
65 template<class T>
66 class Table :
67  public Clonable
68 {
69 protected:
70  size_t nRow_, nCol_;
71  std::vector< std::vector<T> > data_;
72  std::vector<std::string> rowNames_;
73  std::vector<std::string> colNames_;
74 
75 public:
83  Table(size_t nRow, size_t nCol) :
84  nRow_(nRow),
85  nCol_(nCol),
86  data_(nCol),
87  rowNames_(),
88  colNames_()
89  {
90  for (size_t i = 0; i < nCol; i++)
91  {
92  data_[i].resize(nRow);
93  }
94  }
95 
103  Table(const std::vector<std::string>& colNames) :
104  nRow_(0),
105  nCol_(colNames.size()),
106  data_(colNames.size()),
107  rowNames_(),
108  colNames_()
109  {
110  setColumnNames(colNames); // May throw an exception.
111  }
112 
113 
114  Table(const Table& table) :
115  nRow_(table.nRow_),
116  nCol_(table.nCol_),
117  data_(table.data_),
118  rowNames_(table.rowNames_),
119  colNames_(table.colNames_)
120  {}
121 
122  Table(const std::vector<std::vector<T> >& vt) :
123  nRow_(vt.size() == 0 ? 0 : vt[0].size()),
124  nCol_(vt.size()),
125  data_(vt),
126  rowNames_(),
127  colNames_()
128  {}
129 
130  Table& operator=(const Table& table)
131  {
132  nRow_ = table.nRow_;
133  nCol_ = table.nCol_;
134  data_ = table.data_;
135  rowNames_ = table.rowNames_;
136  colNames_ = table.colNames_;
137  return *this;
138  }
139 
140  Table& operator=(const std::vector<std::vector<T> >& vt)
141  {
142  nCol_ = vt.size();
143  if (vt.size() == 0)
144  {
145  nRow_ = 0;
146  data_.clear();
147  }
148  else
149  {
150  nRow_ = vt[0].size();
151  data_ = vt;
152  }
153 
154  rowNames_.clear();
155  colNames_.clear();
156  return *this;
157  }
158 
159  Table* clone() const { return new Table(*this); }
160 
161  virtual ~Table() {}
162 
163 public:
168  const std::vector< std::vector<T> >& getData() const
169  {
170  return data_;
171  }
172 
173 
180  T& operator()(size_t rowIndex, size_t colIndex)
181  {
182  if (colIndex >= nCol_)
183  throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", colIndex, 0, nCol_ - 1);
184  if (rowIndex >= data_[colIndex].size())
185  throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", rowIndex, 0, data_[colIndex].size() - 1);
186  return data_[colIndex][rowIndex];
187  }
188 
195  const T& operator()(size_t rowIndex, size_t colIndex) const
196  {
197  if (colIndex >= nCol_)
198  throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", colIndex, 0, nCol_ - 1);
199  if (rowIndex >= data_[colIndex].size())
200  throw IndexOutOfBoundsException("Table::operator(size_t, size_t).", rowIndex, 0, data_[colIndex].size() - 1);
201  return data_[colIndex][rowIndex];
202  }
203 
212  T& operator()(const std::string& rowName, const std::string& colName)
213  {
214  if (rowNames_.size() == 0)
215  throw NoTableRowNamesException("Table::operator(const string &, const string &).");
216  if (colNames_.size() == 0)
217  throw NoTableColumnNamesException("Table::operator(const string &, const string &).");
218  try
219  {
220  size_t rowIndex = VectorTools::which(rowNames_, rowName);
221  size_t colIndex = VectorTools::which(colNames_, colName);
222  return (*this)(rowIndex, colIndex);
223  }
225  {
226  throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
227  }
228  }
229 
239  const T& operator()(const std::string& rowName, const std::string& colName) const
240  {
241  if (rowNames_.size() == 0)
242  throw NoTableRowNamesException("Table::operator(const string &, const string &).");
243  if (colNames_.size() == 0)
244  throw NoTableColumnNamesException("Table::operator(const string &, const string &).");
245  try
246  {
247  size_t rowIndex = VectorTools::which(rowNames_, rowName);
248  size_t colIndex = VectorTools::which(colNames_, colName);
249  return (*this)(rowIndex, colIndex);
250  }
252  {
253  throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
254  }
255  }
256 
257 
266  T& operator()(const std::string& rowName, size_t colIndex)
267  {
268  if (rowNames_.size() == 0)
269  throw NoTableRowNamesException("Table::operator(const string &, size_t).");
270  if (colIndex >= nCol_)
271  throw IndexOutOfBoundsException("Table::operator(const string &, size_t).", colIndex, 0, nCol_ - 1);
272  try
273  {
274  size_t rowIndex = VectorTools::which(rowNames_, rowName);
275  return (*this)(rowIndex, colIndex);
276  }
278  {
279  throw TableNameNotFoundException("Table::operator(const string &, size_t).", *ex.getElement());
280  }
281  }
282 
283 
292  const T& operator()(const std::string& rowName, size_t colIndex) const
293  {
294  if (rowNames_.size() == 0)
295  throw NoTableRowNamesException("Table::operator(const string &, size_t).");
296  if (colIndex >= nCol_)
297  throw IndexOutOfBoundsException("Table::operator(const string &, size_t).", colIndex, 0, nCol_ - 1);
298  try
299  {
300  size_t rowIndex = VectorTools::which(rowNames_, rowName);
301  return (*this)(rowIndex, colIndex);
302  }
304  {
305  throw TableNameNotFoundException("Table::operator(const string &, size_t).", *ex.getElement());
306  }
307  }
308 
309 
318  T& operator()(size_t rowIndex, const std::string& colName)
319  {
320  if (colNames_.size() == 0)
321  throw NoTableColumnNamesException("Table::operator(size_t, const string &).");
322  try
323  {
324  size_t colIndex = VectorTools::which(colNames_, colName);
325  if (rowIndex >= data_[colIndex].size())
326  throw IndexOutOfBoundsException("Table::operator(size_t, const string &).", rowIndex, 0, data_[colIndex].size() - 1);
327  return (*this)(rowIndex, colIndex);
328  }
330  {
331  throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
332  }
333  }
334 
335 
344  const T& operator()(size_t rowIndex, const std::string& colName) const
345  {
346  if (colNames_.size() == 0)
347  throw NoTableColumnNamesException("Table::operator(size_t, const string &).");
348  try
349  {
350  size_t colIndex = VectorTools::which(colNames_, colName);
351  if (rowIndex >= data_[colIndex].size())
352  throw IndexOutOfBoundsException("Table::operator(size_t, const string &).", rowIndex, 0, data_[colIndex].size() - 1);
353  return (*this)(rowIndex, colIndex);
354  }
356  {
357  throw TableNameNotFoundException("Table::operator(const string &, const string &).", *ex.getElement());
358  }
359  }
360 
370  size_t getNumberOfColumns() const { return nCol_; }
371 
379  void setColumnNames(const std::vector<std::string>& colNames)
380  {
381  if (!VectorTools::isUnique(colNames))
382  throw DuplicatedTableColumnNameException("Table::setColumnNames(...). Column names must be unique.");
383  if (colNames.size() != nCol_)
384  throw DimensionException("Table::setColumnNames.", colNames.size(), nCol_);
385  else
386 
387  colNames_ = colNames;
388  }
389 
396  const std::vector<std::string>& getColumnNames() const
397  {
398  if (colNames_.size() == 0)
399  throw NoTableColumnNamesException("Table::getColumnNames().");
400  return colNames_;
401  }
402 
403  std::vector<std::string>& getColumnNames()
404  {
405  if (colNames_.size() == 0)
406  throw NoTableColumnNamesException("Table::getColumnNames().");
407  return colNames_;
408  }
409 
418  std::string getColumnName(size_t index) const
419  {
420  if (colNames_.size() == 0)
421  throw NoTableColumnNamesException("Table::getColumnName(size_t).");
422  if (index >= nCol_)
423  throw IndexOutOfBoundsException("Table::getColumnName(size_t).", index, 0, nCol_ - 1);
424  return colNames_[index];
425  }
426 
427 
431  bool hasColumnNames() const { return colNames_.size() != 0; }
432 
438  std::vector<T>& getColumn(size_t index)
439  {
440  if (index >= nCol_)
441  throw IndexOutOfBoundsException("Table::getColumn(size_t).", index, 0, nCol_ - 1);
442  return data_[index];
443  }
444 
450  const std::vector<T>& getColumn(size_t index) const
451  {
452  if (index >= nCol_)
453  throw IndexOutOfBoundsException("Table::getColumn(size_t).", index, 0, nCol_ - 1);
454  return data_[index];
455  }
456 
457 
464  std::vector<T>& getColumn(const std::string& colName)
465  {
466  if (colNames_.size() == 0)
467  throw NoTableColumnNamesException("Table::getColumn(const string &).");
468  try
469  {
470  size_t colIndex = VectorTools::which(colNames_, colName);
471  return data_[colIndex];
472  }
474  {
475  throw TableColumnNameNotFoundException("Table::getColumn(const string &).", colName);
476  }
477  }
478 
485  const std::vector<T>& getColumn(const std::string& colName) const
486  {
487  if (colNames_.size() == 0)
488  throw NoTableColumnNamesException("Table::getColumn(const string &).");
489  try
490  {
491  size_t colIndex = VectorTools::which(colNames_, colName);
492  return data_[colIndex];
493  }
495  {
496  throw TableColumnNameNotFoundException("Table::getColumn(const string &).", colName);
497  }
498  }
499 
500 
507  bool hasColumn(const std::string& colName) const
508  {
509  if (colNames_.size() == 0)
510  return false;
511  for (size_t i = 0; i < colNames_.size(); i++)
512  {
513  if ((colNames_)[i] == colName)
514  return true;
515  }
516  return false;
517  }
518 
519 
526  void deleteColumn(size_t index)
527  {
528  if (index >= nCol_)
529  throw IndexOutOfBoundsException("Table::deleteColumn(size_t).", index, 0, nCol_ - 1);
530  data_.erase(data_.begin() + (long)index);
531  if (colNames_.size() != 0)
532  colNames_.erase(colNames_.begin() + (long)(index));
533  nCol_--;
534  }
535 
543  void deleteColumn(const std::string& colName)
544  {
545  if ((colNames_.size() == 0))
546  throw NoTableColumnNamesException("Table::deleteColumn(const string &).");
547  try
548  {
549  size_t colIndex = VectorTools::which(colNames_, colName);
550  data_.erase(data_.begin() + (size_t)(colIndex));
551  colNames_.erase(colNames_.begin() + (size_t)(colIndex));
552  nCol_--;
553  }
555  {
556  throw TableColumnNameNotFoundException("Table::deleteColumn(const string &).", colName);
557  }
558  }
559 
560 
569  void addColumn(const std::vector<T>& newColumn, int pos = -1)
570  {
571  if (pos > (int)nCol_)
572  throw DimensionException("Table::addColumn.", (size_t)pos, nCol_);
573  if (pos == -1)
574  pos = (int)nCol_;
575 
576  if (colNames_.size())
577  throw TableColumnNamesException("Table::addColumn. Table has column names.");
578  if (newColumn.size() != nRow_)
579  throw DimensionException("Table::addColumn.", newColumn.size(), nRow_);
580 
581  data_.insert(data_.begin() + pos, newColumn);
582  nCol_++;
583  }
584 
595  void addColumn(const std::string& colName, const std::vector<T>& newColumn, int pos = -1)
596  {
597  if (pos > (int)nCol_)
598  throw DimensionException("Table::addColumn.", pos, nCol_);
599  if (pos == -1)
600  pos = nCol_;
601 
602  if ((colNames_.size() == 0) && (nCol_ != 0))
603  throw NoTableColumnNamesException("Table::addColumn. Table has column names.");
604 
605  if (newColumn.size() != nRow_)
606  throw DimensionException("Table::addColumn.", newColumn.size(), nRow_);
607  if (nCol_ > 0 && find(colNames_.begin(), colNames_.end(), colName) != colNames_.end())
608  throw DuplicatedTableColumnNameException("Table::addColumn(const string &, const std::vector<string> &). Column names must be unique.");
609 
610  colNames_.insert(colNames_.begin() + pos, colName);
611  data_.insert(data_.begin() + pos, newColumn);
612  nCol_++;
613  }
614 
624  void addColumn(std::string& st, const std::string& sep = "\t", int pos = -1, int rowCol = -1)
625  {
626  if (pos > (int)nCol_)
627  throw DimensionException("Table::addColumn.", (size_t)pos, nCol_);
628  if (pos == -1)
629  pos = (int)nCol_;
630 
631  StringTokenizer stok(st, sep, false, true);
632  std::vector<std::string> row(stok.getTokens().begin(), stok.getTokens().end());
633 
634  if (row.size() != nRow_ + (rowCol >= 0) ? 1 : 0)
635  throw BadIntegerException("Table::addColumn. Bad number of rows: ", (int)row.size());
636 
637  std::vector<T> newColumn;
638 
639  for (size_t i = 0; i < row.size(); i++)
640  {
641  if ((int)i == rowCol)
642  {
643  std::string colName = row[i];
644  if (find(colNames_.begin(), colNames_.end(), colName) != colNames_.end())
645  throw DuplicatedTableColumnNameException("Table::addColumn(const std::vector<string> &). Column names must be unique.");
646 
647  colNames_.insert(colNames_.begin() + (long)pos, colName);
648  }
649  else
650  {
651  std::stringstream ss(row[i]);
652  T t;
653  ss >> t;
654  newColumn.push_back(t);
655  }
656  }
657  data_.insert(data_.begin() + pos, newColumn);
658 
659  nCol_++;
660  }
661 
662 
671  void setColumn(const std::vector<T>& newColumn, size_t pos)
672  {
673  if (pos >= nCol_)
674  throw DimensionException("Table::setColumn.", pos, nCol_);
675 
676  if (newColumn.size() != nRow_)
677  throw DimensionException("Table::setColumn.", newColumn.size(), nRow_);
678 
679  data_[pos] = newColumn;
680  }
681 
692  void setColumn(const std::string& colName, const std::vector<T>& newColumn, size_t pos)
693  {
694  if (pos >= nCol_)
695  throw DimensionException("Table::setColumn.", pos, nCol_);
696 
697  if (colNames_.size() == 0)
698  throw NoTableColumnNamesException("Table::setColumn. Table has column names.");
699 
700  if (newColumn.size() != nRow_)
701  throw DimensionException("Table::setColumn.", newColumn.size(), nRow_);
702 
703  if (find(colNames_.begin(), colNames_.end(), colName) != colNames_.end() &&
704  find(colNames_.begin(), colNames_.end(), colName) != colNames_.begin() + pos)
705  throw DuplicatedTableColumnNameException("Table::setColumn(const string &, const std::vector<T> &, size_t). Column names must be unique.");
706 
707  colNames_[pos] = colName;
708  data_[pos] = newColumn;
709  }
710 
722  size_t getNumberOfRows() const { return nRow_; }
723 
731  void setRowNames(const std::vector<std::string>& rowNames)
732  {
733  if (!VectorTools::isUnique(rowNames))
734  {
735  throw DuplicatedTableRowNameException("Table::setRowNames(...). Row names must be unique.");
736  }
737  if (rowNames.size() != nRow_)
738  throw DimensionException("Table::setRowNames.", rowNames.size(), nRow_);
739  else
740  {
741  rowNames_ = rowNames;
742  }
743  }
744 
745 
752  std::vector<std::string> getRowNames()
753  {
754  if (rowNames_.size() == 0)
755  throw NoTableRowNamesException("Table::getRowNames().");
756  return rowNames_;
757  }
758 
759  const std::vector<std::string>& getRowNames() const
760  {
761  if (rowNames_.size() == 0)
762  throw NoTableRowNamesException("Table::getRowNames().");
763  return rowNames_;
764  }
765 
766 
773  bool hasRow(const std::string& rowName) const
774  {
775  if (rowNames_.size() == 0)
776  return false;
777  for (size_t i = 0; i < rowNames_.size(); i++)
778  {
779  if ((rowNames_)[i] == rowName)
780  return true;
781  }
782  return false;
783  }
784 
785 
794  std::string getRowName(size_t index) const
795  {
796  if (rowNames_.size() == 0)
797  throw NoTableRowNamesException("Table::getRowName(size_t).");
798  if (index >= nRow_)
799  throw IndexOutOfBoundsException("Table::getRowName(size_t).", index, 0, nRow_ - 1);
800  return (rowNames_)[index];
801  }
802 
803 
807  bool hasRowNames() const { return rowNames_.size() != 0; }
808 
814  std::vector<T> getRow(size_t index) const
815  {
816  if (index >= nRow_)
817  throw IndexOutOfBoundsException("Table::getRow(size_t).", index, 0, nRow_ - 1);
818  std::vector<T> row;
819  for (size_t i = 0; i < nCol_; i++)
820  {
821  row.push_back(data_[i][index]);
822  }
823  return row;
824  }
825 
826 
833  std::vector<T> getRow(const std::string& rowName) const
834  {
835  if ((rowNames_.size() == 0))
836  throw NoTableRowNamesException("Table::getRow(const string &).");
837  try
838  {
839  size_t rowIndex = VectorTools::which(rowNames_, rowName);
840  std::vector<T> row;
841  for (size_t i = 0; i < nCol_; i++)
842  {
843  row.push_back(data_[i][rowIndex]);
844  }
845  return row;
846  }
848  {
849  throw TableRowNameNotFoundException("Table::getRow(const string &).", rowName);
850  }
851  }
852 
853 
860  void deleteRow(size_t index)
861  {
862  for (size_t j = 0; j < nCol_; j++)
863  {
864  std::vector<T>* column = &data_[j];
865  if (index >= column->size())
866  throw IndexOutOfBoundsException("Table::deleteRow(size_t).", index, 0, column->size() - 1);
867  column->erase(column->begin() + index);
868  }
869  if (rowNames_.size() != 0)
870  rowNames_.erase(rowNames_.begin() + index);
871  nRow_--;
872  }
873 
881  void deleteRows(size_t index, size_t len)
882  {
883  for (size_t j = 0; j < nCol_; j++)
884  {
885  std::vector<T>* column = &data_[j];
886  if (index >= column->size())
887  throw IndexOutOfBoundsException("Table::deleteRow(size_t).", index, 0, column->size() - 1);
888  column->erase(column->begin() + (long)index, column->begin() + long(index + len));
889  }
890  if (rowNames_.size() != 0)
891  rowNames_.erase(rowNames_.begin() + long(index), rowNames_.begin() + long(index + len));
892  nRow_--;
893  }
894 
895 
903  void deleteRow(const std::string& rowName)
904  {
905  if ((rowNames_.size() == 0))
906  throw NoTableRowNamesException("Table::deleteRow(const string &).");
907  try
908  {
909  size_t rowIndex = VectorTools::which(rowNames_, rowName);
910  for (size_t j = 0; j < nCol_; j++)
911  {
912  std::vector<T>* column = &data_[j];
913  column->erase(column->begin() + rowIndex);
914  }
915  rowNames_.erase(rowNames_.begin() + rowIndex);
916  nRow_--;
917  }
919  {
920  throw TableRowNameNotFoundException("Table::deleteRow(const string &).", rowName);
921  }
922  }
923 
924 
931  void addRow(const std::vector<T>& newRow, int pos = -1)
932  {
933  if (pos > (int)nRow_)
934  throw DimensionException("Table::addRow.", pos, nRow_);
935 
936  if (pos == -1)
937  pos = nRow_;
938 
939  if (rowNames_.size() != 0)
940  throw TableRowNamesException("Table::addRow. Table has row names.");
941  if (newRow.size() != nCol_)
942  throw DimensionException("Table::addRow.", newRow.size(), nCol_);
943  for (size_t j = 0; j < nCol_; j++)
944  {
945  data_[j].insert(data_[j].begin() + (size_t)pos, newRow[j]);
946  }
947  nRow_++;
948  }
949 
957  void addRow(const std::string& rowName, const std::vector<T>& newRow, int pos = -1)
958  {
959  if (pos > (int)nRow_)
960  throw DimensionException("Table::addRow.", pos, nRow_);
961  if (pos == -1)
962  pos = nRow_;
963 
964  if ((rowNames_.size() == 0) && (nRow_ != 0))
965  throw NoTableRowNamesException("Table::addRow. Table has row names.");
966 
967  if (newRow.size() != nCol_)
968  throw DimensionException("Table::addRow.", newRow.size(), nCol_);
969  if (nRow_ > 0 && find(rowNames_.begin(), rowNames_.end(), rowName) != rowNames_.end())
970  throw DuplicatedTableRowNameException("Table::addRow(const string &, const std::vector<string> &). Row names must be unique.");
971  rowNames_.insert(rowNames_.begin() + (size_t)pos, rowName);
972  for (size_t j = 0; j < nCol_; j++)
973  {
974  data_[j].insert(data_[j].begin() + (size_t)pos, newRow[j]);
975  }
976  nRow_++;
977  }
978 
988  void addRow(std::string& st, const std::string& sep = "\t", int pos = -1, int rowCol = -1)
989  {
990  if (pos > (int)nRow_)
991  throw DimensionException("Table::addRow.", (size_t)pos, nRow_);
992  if (pos == -1)
993  pos = (int)nRow_;
994 
995  StringTokenizer stok(st, sep, false, true);
996  std::vector<std::string> row(stok.getTokens().begin(), stok.getTokens().end());
997 
998  if (row.size() != nCol_ + (rowCol >= 0) ? 1 : 0)
999  throw BadIntegerException("Table::addRow. Bad number of columns: ", (int)row.size());
1000 
1001  size_t id = 0;
1002 
1003  for (size_t i = 0; i < row.size(); i++)
1004  {
1005  if ((int)i == rowCol)
1006  {
1007  std::string rowName = row[i];
1008  if (find(rowNames_.begin(), rowNames_.end(), rowName) != rowNames_.end())
1009  throw DuplicatedTableRowNameException("Table::addRow(const std::vector<string> &). Row names must be unique.");
1010 
1011  rowNames_.insert(rowNames_.begin() + (long)pos, rowName);
1012  }
1013  else
1014  {
1015  std::stringstream ss(row[i]);
1016  T t;
1017  ss >> t;
1018  data_[id].insert(data_[id].begin() + (long)pos, t);
1019  id++;
1020  }
1021  }
1022  nRow_++;
1023  }
1024 
1025 
1028 public:
1046  static Table<T>* read(std::istream& in, bool byRow, const std::string& sep = "\t", bool header = true, int names = -1)
1047  {
1048  std::string firstLine = FileTools::getNextLine(in);
1049  StringTokenizer st1(firstLine, sep, false, true);
1050  std::vector<std::string> row1(st1.getTokens().begin(), st1.getTokens().end());
1051  size_t nCol = row1.size();
1052  Table<T>* dt;
1053 
1054  if (header)
1055  {
1056  // Use first line as header.
1057  if (byRow)
1058  {
1059  dt = new Table<T>(0, nCol);
1060  dt->setColumnNames(row1);
1061  }
1062  else
1063  {
1064  dt = new Table<T>(nCol, 0);
1065  dt->setRowNames(row1);
1066  }
1067  }
1068  else
1069  {
1070  if (byRow)
1071  {
1072  dt = new Table<T>(0, nCol - (names >= 0 ? 1 : 0));
1073  dt->addRow(firstLine, sep, names);
1074  }
1075  else
1076  {
1077  dt = new Table<T>(nCol - (names >= 0 ? 1 : 0), 0);
1078  dt->addColumn(firstLine, sep, names);
1079  }
1080  }
1081 
1082  // Now read each line:
1083  std::string line = FileTools::getNextLine(in);
1084 
1085  while (!TextTools::isEmpty(line))
1086  {
1087  if (byRow)
1088  dt->addRow(line, sep, names);
1089  else
1090  dt->addColumn(line, sep, names);
1091 
1092  line = FileTools::getNextLine(in);
1093  }
1094  return dt;
1095  }
1096 
1097 
1107  static void write(const Table& data, std::ostream& out, bool byRow, const std::string& sep = "\t", bool alignHeaders = false)
1108  {
1109  size_t n = (byRow ? data.getNumberOfColumns() : data.getNumberOfRows());
1110  if (n == 0)
1111  return;
1112  size_t m = (byRow ? data.getNumberOfRows() : data.getNumberOfColumns());
1113 
1114  bool frontNames = ((byRow && data.hasRowNames()) || (!byRow && data.hasColumnNames()));
1115 
1116  if ((byRow && data.hasColumnNames()) || (!byRow && data.hasRowNames()))
1117  { // Write header
1118  std::vector<std::string> names = (byRow ? data.getColumnNames() : data.getRowNames());
1119 
1120  if (alignHeaders && frontNames)
1121  out << sep;
1122  out << names[0];
1123  for (size_t i = 1; i < n; i++)
1124  {
1125  out << sep << names[i];
1126  }
1127  out << std::endl;
1128  }
1129 
1130  // now write each row (or column):
1131 
1132  for (size_t i = 0; i < m; i++)
1133  {
1134  if (frontNames)
1135  {
1136  out << (byRow ? data.getRowName(i) : data.getColumnName(i)) << sep;
1137  }
1138 
1139  out << (byRow ? data(i, 0) : data(0, i));
1140  for (size_t j = 1; j < n; j++)
1141  {
1142  out << sep << (byRow ? data(i, j) : data(j, i));
1143  }
1144  out << std::endl;
1145  }
1146  }
1147 
1148  static void write(const Table& data, bpp::OutputStream& out, bool byRow, const std::string& sep = "\t", bool alignHeaders = false)
1149  {
1150  size_t n = (byRow ? data.getNumberOfColumns() : data.getNumberOfRows());
1151  if (n == 0)
1152  return;
1153  size_t m = (byRow ? data.getNumberOfRows() : data.getNumberOfColumns());
1154 
1155  bool frontNames = ((byRow && data.hasRowNames()) || (!byRow && data.hasColumnNames()));
1156 
1157  if ((byRow && data.hasColumnNames()) || (!byRow && data.hasRowNames()))
1158  { // Write header
1159  std::vector<std::string> names = (byRow ? data.getColumnNames() : data.getRowNames());
1160 
1161  if (alignHeaders && frontNames)
1162  out << sep;
1163  out << names[0];
1164  for (size_t i = 1; i < n; i++)
1165  {
1166  out << sep << names[i];
1167  }
1168  out.endLine();
1169  }
1170 
1171  // now write each row (or column):
1172 
1173  for (size_t i = 0; i < m; i++)
1174  {
1175  if (frontNames)
1176  out << (byRow ? data.getRowName(i) : data.getColumnName(i)) << sep;
1177 
1178  out << (byRow ? data(i, 0) : data(0, i));
1179  for (size_t j = 1; j < n; j++)
1180  {
1181  out << sep << (byRow ? data(i, j) : data(j, i));
1182  }
1183  out.endLine();
1184  }
1185  }
1186 };
1187 } // end of namespace bpp.
1188 #endif // BPP_NUMERIC_TABLE_H
Number exception: integers.
Definition: Exceptions.h:116
The Clonable interface (allow an object to be cloned).
Definition: Clonable.h:103
Exception thrown when a dimension problem occured.
Excpetion thrown when attempting to duplicate a column name.
Exception thrown when attempting to duplicate a row name.
Exception thrown when a given element was not found in the vector.
static std::string getNextLine(std::istream &in)
Get the next non-blanck line of a stream.
Definition: FileTools.cpp:145
Index out of bounds exception class.
Definition: Exceptions.h:170
Exception thrown when trying to retrieve a column by its name and no column names have been specified...
Exception thrown when trying to retrieve a row by its name and no row names have been specified.
OutputStream interface.
Definition: OutputStream.h:67
virtual OutputStream & endLine()=0
A tokenizer for strings.
const std::deque< std::string > & getTokens() const
Retrieve all tokens.
Exception thrown when a given column name is not found is a DataTable object.
General exception class dealing with column names.
Exception thrown when a given name is not found is a DataTable object.
Exception thrown when a given row name is not found is a DataTable object.
General exception class dealing with row names.
This class corresponds to a 'dataset', i.e. a table with data by rows and variable by columns.
Definition: Table.h:68
const T & operator()(size_t rowIndex, const std::string &colName) const
Definition: Table.h:344
void addColumn(const std::string &colName, const std::vector< T > &newColumn, int pos=-1)
Add a new column.
Definition: Table.h:595
const T & operator()(size_t rowIndex, size_t colIndex) const
Definition: Table.h:195
void deleteRows(size_t index, size_t len)
Delete the given rows.
Definition: Table.h:881
std::vector< std::string > rowNames_
Definition: Table.h:72
std::vector< T > getRow(size_t index) const
Definition: Table.h:814
size_t getNumberOfColumns() const
Definition: Table.h:370
std::vector< T > & getColumn(size_t index)
Definition: Table.h:438
size_t nRow_
Definition: Table.h:70
T & operator()(const std::string &rowName, size_t colIndex)
Definition: Table.h:266
std::string getColumnName(size_t index) const
Get a given column name.
Definition: Table.h:418
void deleteRow(size_t index)
Delete the given row.
Definition: Table.h:860
const std::vector< std::string > & getColumnNames() const
Get the column names of this table.
Definition: Table.h:396
Table * clone() const
Create a copy of this object and send a pointer to it.
Definition: Table.h:159
Table & operator=(const std::vector< std::vector< T > > &vt)
Definition: Table.h:140
void setRowNames(const std::vector< std::string > &rowNames)
Set the row names of this table.
Definition: Table.h:731
std::vector< T > & getColumn(const std::string &colName)
Definition: Table.h:464
bool hasRow(const std::string &rowName) const
Tell is a given row exists.
Definition: Table.h:773
size_t nCol_
Definition: Table.h:70
Table(const std::vector< std::string > &colNames)
Build a new void Table object with named columns.
Definition: Table.h:103
void deleteRow(const std::string &rowName)
Delete the given row.
Definition: Table.h:903
void deleteColumn(size_t index)
Delete the given column.
Definition: Table.h:526
T & operator()(size_t rowIndex, size_t colIndex)
Definition: Table.h:180
void setColumn(const std::vector< T > &newColumn, size_t pos)
Set a new column.
Definition: Table.h:671
std::vector< std::string > colNames_
Definition: Table.h:73
const std::vector< std::vector< T > > & getData() const
Definition: Table.h:168
const std::vector< T > & getColumn(size_t index) const
Definition: Table.h:450
Table(const std::vector< std::vector< T > > &vt)
Definition: Table.h:122
bool hasColumnNames() const
Definition: Table.h:431
std::string getRowName(size_t index) const
Get a given row name.
Definition: Table.h:794
Table(const Table &table)
Definition: Table.h:114
std::vector< T > getRow(const std::string &rowName) const
Definition: Table.h:833
bool hasColumn(const std::string &colName) const
Tell is a given column exists.
Definition: Table.h:507
const std::vector< T > & getColumn(const std::string &colName) const
Definition: Table.h:485
const T & operator()(const std::string &rowName, size_t colIndex) const
Definition: Table.h:292
std::vector< std::string > & getColumnNames()
Definition: Table.h:403
std::vector< std::vector< T > > data_
Definition: Table.h:71
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:957
void deleteColumn(const std::string &colName)
Delete the given column.
Definition: Table.h:543
std::vector< std::string > getRowNames()
Get the row names of this table.
Definition: Table.h:752
static Table< T > * read(std::istream &in, bool byRow, const std::string &sep="\t", bool header=true, int names=-1)
Read a table form a stream in CSV-like.
Definition: Table.h:1046
void setColumn(const std::string &colName, const std::vector< T > &newColumn, size_t pos)
Set a new column.
Definition: Table.h:692
virtual ~Table()
Definition: Table.h:161
void addColumn(const std::vector< T > &newColumn, int pos=-1)
Add a new column.
Definition: Table.h:569
static void write(const Table &data, std::ostream &out, bool byRow, const std::string &sep="\t", bool alignHeaders=false)
Write a Table object to stream in CVS-like format.
Definition: Table.h:1107
void addRow(std::string &st, const std::string &sep="\t", int pos=-1, int rowCol=-1)
Add a new row.
Definition: Table.h:988
Table & operator=(const Table &table)
Definition: Table.h:130
static void write(const Table &data, bpp::OutputStream &out, bool byRow, const std::string &sep="\t", bool alignHeaders=false)
Definition: Table.h:1148
void setColumnNames(const std::vector< std::string > &colNames)
Set the column names of this table.
Definition: Table.h:379
size_t getNumberOfRows() const
Definition: Table.h:722
T & operator()(const std::string &rowName, const std::string &colName)
Definition: Table.h:212
bool hasRowNames() const
Definition: Table.h:807
const T & operator()(const std::string &rowName, const std::string &colName) const
Definition: Table.h:239
T & operator()(size_t rowIndex, const std::string &colName)
Definition: Table.h:318
Table(size_t nRow, size_t nCol)
Build a new void Table object with nRow rows and nCol columns.
Definition: Table.h:83
void addRow(const std::vector< T > &newRow, int pos=-1)
Add a new row.
Definition: Table.h:931
const std::vector< std::string > & getRowNames() const
Definition: Table.h:759
void addColumn(std::string &st, const std::string &sep="\t", int pos=-1, int rowCol=-1)
Add a new column.
Definition: Table.h:624
static bool isUnique(const std::vector< T > &v)
Tell if the std::vector as unique elements.
Definition: VectorTools.h:508
static size_t which(const std::vector< T > &v, const T &which)
Send the position of the first occurence of 'which'.
Definition: VectorTools.h:439
bool isEmpty(const std::string &s)
Tell if a string is empty. A string is considered to be 'empty' if it is only made of white spaces.
Definition: TextTools.cpp:58