我的问题是如何初始化一个特征矩阵,但 NOT 这样:
matrix << 1,0,1,0,
1,0,1,0,
1,0,1,0,
我有一个看起来像上面的矩阵(逗号或没有逗号无关紧要) 存储在txt文件中。
我已经编写了一个函数来读取每一行并将其放入向量中 现在我想用这个数据创建一个矩阵
但它没有用,我找不到任何解释如何在不写入值的情况下将数据分配给矩阵的页面。(如上例所示)
我需要的只是来自我的文件中的特征矩阵
中的数据到目前为止我尝试了什么:(PS:有了迭代器的想法,但我想用真正的大矩阵需要太长时间,我只是用1-2维矩阵尝试了这个例子)
int readFromFile (const char * path, vector <string> & mv)
{
fstream file;
string line;
file.open(path);
while (getline(file,line))
{
mv.push_back(line);
}
file.close();
return 0;
}
typedef Matrix <int, 1, 2> MyMatrix;
int fromVectoEigen (vector<string> & source, MyMatrix & target)
{ //for (int i = source.size(); i<0 ; i--)
//{
string valuerow = source.back();
string::iterator it = valuerow.begin();
target.row(0)<< *it;
target.row(0)<<*it+1;
//source.pop_back();
//}
return 0;
}
不幸的是,只能说Matrix.row(i) = vector.back()
无效。
答案 0 :(得分:4)
以下代码适用于包含任意大小矩阵的文件:
#include <iostream>
#include <fstream>
#include <string>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
#define MAXBUFSIZE ((int) 1e6)
MatrixXd readMatrix(const char *filename)
{
int cols = 0, rows = 0;
double buff[MAXBUFSIZE];
// Read numbers from file into buffer.
ifstream infile;
infile.open(filename);
while (! infile.eof())
{
string line;
getline(infile, line);
int temp_cols = 0;
stringstream stream(line);
while(! stream.eof())
stream >> buff[cols*rows+temp_cols++];
if (temp_cols == 0)
continue;
if (cols == 0)
cols = temp_cols;
rows++;
}
infile.close();
rows--;
// Populate matrix with numbers.
MatrixXd result(rows,cols);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
result(i,j) = buff[ cols*i+j ];
return result;
};
问候。
答案 1 :(得分:4)
我刚刚发布了Eigen包的扩展,可以完成你想要的一些。它定义了&gt;&gt;运营商,所以你可以说:
MatrixXd A(5,5); cin&gt;&gt; A;
它还允许您将VectorXd指定为等于std :: vector。可以找到Eigen的扩展版本here。但是,它(还)不允许您将std :: vector复制到不是向量的MatrixXd对象中。您想要的功能是Eigen中的Map函数。
答案 2 :(得分:3)
我想我找到了解决方案!它不是快速或有效但它的工作原理:
#include "topo.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <iterator>
#include <algorithm>
using namespace std;
using namespace Eigen;
/**Read data from File and store it in vector as string**/
int readFromFile (const char * path, vector <string> & mv) // muss vector vorher resized werden? wenn ja lese zeilenanzahl
{
fstream file;
string line;
file.open(path);
while (getline(file,line)) // lese zeile für zeile
{
mv.push_back(line); //fülle vector von hinten last in first
}
file.close();
return 0;
}
typedef Matrix <int, 4, 4> MyMatrix; // Matrix später dynamisch
/**Parsing data to be used as Eigen Matrix**/
int fromVectoEigen (vector<string> & source, MyMatrix & target)
{ /**convert string to int and write it to the two dimensional array **/
int array [4][4]; // noch resize nach vectorsize -->matrizen sind quadratisch
int i = source.size();
for ( i= i-1 ; i >= 0 ; i-- ) // da nur von hintern auf vector zugreifbar auch von hinten bei array anfangen
{
string myString = source.back(); // leztzes Element von Vector als String
stringstream ssin(myString);
int j = 0;
while (ssin.good() && j < 4) // auch hier vectorsize später dynamisch
{
ssin >> array[j][i]; // fülle spalten in i.ter zeile
++j;
}
source.pop_back(); //lösche letztes element
}
// cout<<array[0][0]<<array[1][0]<<array[2][0]<<array[3][0]<<'\n';
// cout<<array[0][1]<<array[1][1]<<array[2][1]<<array[3][1]<<'\n';
// cout<<array[0][2]<<array[1][2]<<array[2][2]<<array[3][2]<<'\n';
// cout<<array[0][3]<<array[1][3]<<array[2][3]<<array[3][3]<<'\n';
//
/** from 2 dimensional array to one dimensional array**/
int newarray [16]; // vectorsize * vectorsize
int k = 0;
for ( int i = 0 ; i< 4 ; i++) // vectorsize
{ for (int j = 0 ; j<4; j++) // vectorsize
{
newarray[k]=array[j][i];
k++;
}
}
/**create Eigen Matrix from Array**/
target= Map<Matrix4i>(newarray);
target.transposeInPlace();
cout<<target<<'\n';
return 0 ;
}
答案 3 :(得分:3)
我使用逐元素初始化(假设我们知道nrows和ncols):
MatrixXf X = MatrixXf::Zero(nrows,ncols);
ifstream fin ("./data.txt");
if (fin.is_open())
{
for (int row = 0; row < nrows; row++)
for (int col = 0; col < ncols; col++)
{
float item = 0.0;
fin >> item;
X(row, col) = item;
}
fin.close();
}
cout << "X = " << endl << X << endl;
答案 4 :(得分:1)
基于https://eigen.tuxfamily.org/dox/group__TutorialMapClass.html
的示例,仅使用Eigen :: Map来映射来自std :: vector的数据的变体#include <vector>
#include <Eigen/Dense>
std::vector<double> myStdVector;
// Insert code for filling myStdVector here
// ....
// Detect or set number of rows/columns
size_t numRows = 3;
size_t numCols = 7;
typedef Eigen::Map<Eigen::MatrixXd> Mapper;
Mapper myMatrix(&myStdVector.data()[0], numRows, numCols);
答案 5 :(得分:0)
这是我的解决方案:
#include <istream>
#include <string>
#include <sstream>
#include <vector>
#include <fstream>
#include <iostream>
#include <eigen>
using namespace std;
using namespace Eigen;
// load matrix from an ascii text file.
vector<vector<double>> LoadMatrix(istream* filePath, const string &delim = " \t")
{
string line;
string strnum;
auto data = vector<vector<double>>();
// clear first
data.clear();
// parse line by line
while (getline(*filePath, line))
{
data.push_back(vector<double>());
for (string::const_iterator i = line.begin(); i != line.end(); ++i)
{
// If i is not a delim, then append it to strnum
if (delim.find(*i) == string::npos)
{
strnum += *i;
if (i + 1 != line.end()) // If it's the last char, do not continue
continue;
}
// if strnum is still empty, it means the previous char is also a
// delim (several delims appear together). Ignore this char.
if (strnum.empty())
continue;
// If we reach here, we got a number. Convert it to double.
double number;
istringstream(strnum) >> number;
data.back().push_back(number);
strnum.clear();
}
}
return data;
}
Eigen::MatrixXd ConvertToEigenMatrix(std::vector<std::vector<double>> data)
{
Eigen::MatrixXd eMatrix(data.size(), data[0].size());
for (int i = 0; i < data.size(); ++i)
eMatrix.row(i) = Eigen::VectorXd::Map(&data[i][0], data[0].size());
return eMatrix;
}
MatrixXd LoadEigenMatrix(istream* filePath, const string &delim = " \t")
{
auto data = LoadMatrix(filePath, delim);
return ConvertToEigenMatrix(data);
}
答案 6 :(得分:0)
我使用迭代器将向量中的数据收集起来,然后初始化矩阵。转换为vector<double>
似乎是该方法的耗时部分,其速度与上述解决方案大致相同。关于如何改善这一点的想法将很有趣。
template <class T>
using Tmat = Eigen::Matrix<T,Dynamic,Dynamic>;
Tmat<double> txt_to_mat(std::string path, int rows, int cols)
{
std::ifstream fstr(path.c_str());
std::vector<double> data_vec = std::vector<double>{
std::istream_iterator<double>(fstr),
std::istream_iterator<double>()
};
Tmat<double> mat(rows, cols);
for(int i=0; i<rows; i++){
for(int j=0; j<cols; j++){
mat(i,j) = data_vec[i*cols + j];
}
}
return mat;
}