如何阅读CSV文件并分配给Eigen Matrix?

时间:2015-12-13 01:32:59

标签: c++ csv matrix eigen

我尝试将一个大的cvs文件读入Eigen Matrix,在发现有问题的代码下面,它无法检测cvs文件中的每行\ n在矩阵中创建多行。 (它用单行读取整个文件)。不确定代码有什么问题。谁能在这里建议? 我也在寻找一种有效的方法来读取10k行和1k cols的csv文件。不太确定下面的代码是最有效的方法吗?非常感谢您的评论。

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <istream> //DataFile.fail()  function
#include <vector>
#include <set>
#include <string>
using namespace std;


#include <Eigen/Core>
#include <Eigen/Dense>
using namespace Eigen;

 void readCSV(istream &input, vector< vector<string> > &output)
{
    int a = 0;
    int b = 0;

    string csvLine;
    // read every line from the stream
    while( std::getline(input, csvLine) )
    {

        istringstream csvStream(csvLine);
        vector<string> csvColumn;
        MatrixXd mv;
        string csvElement;
        // read every element from the line that is seperated by commas
        // and put it into the vector or strings
        while( getline(csvStream, csvElement, ' ') )
        {
            csvColumn.push_back(csvElement);
            //mv.push_back(csvElement);
            b++;
        }       
        output.push_back(csvColumn);
        a++;
    }
    cout << "a : " << a << " b : " << b << endl;   //a doen't detect '\n'
}

int main(int argc, char* argv[])
{

    cout<< "ELM" << endl;
    //Testing to load dataset from file.
    fstream file("Sample3.csv", ios::in);
    if(!file.is_open())
    {
        cout << "File not found!\n";
        return 1;
    }
    MatrixXd m(3,1000);
    // typedef to save typing for the following object
    typedef vector< vector<string> > csvVector;
    csvVector csvData;

    readCSV(file, csvData);
    // print out read data to prove reading worked
    for(csvVector::iterator i = csvData.begin(); i != csvData.end(); ++i)
    {
        for(vector<string>::iterator j = i->begin(); j != i->end(); ++j)
        {
           m(i,j) = *j; 
           cout << *j << ", ";
        }
        cout << "\n";
    }
}

我还会附上一个示例cvs文件。 https://onedrive.live.com/redir?resid=F1507EBE7BF1C5B!117&authkey=!AMzCnpBqxUyF1BA&ithint=file%2ccsv

3 个答案:

答案 0 :(得分:13)

您可以实际复制粘贴

编写自己的&#34;解析器&#34;

优点:轻量级且可自定义

缺点:可自定义

#include <Eigen/Dense>
#include <vector>
#include <fstream>

using namespace Eigen;

template<typename M>
M load_csv (const std::string & path) {
    std::ifstream indata;
    indata.open(path);
    std::string line;
    std::vector<double> values;
    uint rows = 0;
    while (std::getline(indata, line)) {
        std::stringstream lineStream(line);
        std::string cell;
        while (std::getline(lineStream, cell, ',')) {
            values.push_back(std::stod(cell));
        }
        ++rows;
    }
    return Map<const Matrix<typename M::Scalar, M::RowsAtCompileTime, M::ColsAtCompileTime, RowMajor>>(values.data(), rows, values.size()/rows);
}

<强>用法

MatrixXd A = load_csv<MatrixXd>("C:/Users/.../A.csv");
Matrix3d B = load_csv<Matrix3d>("C:/Users/.../B.csv");
VectorXd v = load_csv<VectorXd>("C:/Users/.../v.csv");

使用armadillo库的解析器

优点:也支持其他格式,而不仅仅是csv

缺点:额外依赖

#include <armadillo>

template <typename M>
M load_csv_arma (const std::string & path) {
    arma::mat X;
    X.load(path, arma::csv_ascii);
    return Eigen::Map<const M>(X.memptr(), X.n_rows, X.n_cols);
}

答案 1 :(得分:0)

根据需要将CSV文件读入您​​的vector < vector >(例如Lucas&#39; answer)。而不是vector< vector<string> >构造,使用vector< vector<double> >或更好的简单vector< double >。要使用vector< vector< double > >有效地将向量矢量分配给特征矩阵,请使用以下命令:

Eigen::MatrixXcd mat(rows, cols);
for(int i = 0; i < rows; i++)
    mat.row(i) = Eigen::Map<Eigen::VectorXd> (csvData[i].data(), cols).cast<complex<double> >();

如果您选择使用vector< double >选项,则会变为:

Eigen::MatrixXcd mat(rows, cols);
mat = Eigen::Map<Eigen::VectorXd> (csvData.data(), rows, cols).cast<complex<double> >().transpose();

答案 2 :(得分:-3)

这将正确读取csv文件:

std::ifstream indata;

indata.open(filename);

std::string                line;
while (getline(indata, line))
{
    std::stringstream          lineStream(line);
    std::string                cell;

    while (std::getline(lineStream, cell, ','))
    {
        //Process cell
    }
}

修改:此外,由于您的csv已满了数字,因此请务必使用std::stod或等效转换,一旦您希望对其进行处理。