2015-12-13 42 views
3

我尝试将一个大的CVS文件读入Eigen Matrix,在发现有问题的代码下面,它无法检测到CVS文件中的每行\ n以在矩阵中创建多行。 (它用单行读取整个文件)。不知道代码有什么问题。任何人都可以在此建议 林也寻找一种有效的方式来读取10k行和1k cols的csv文件。不太确定下面的代码是否是最有效的方式?非常感谢您的评论。如何读取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

+0

截至目前您的分隔符是空的:'”“'。你的意思是:'','? –

+0

嗨卢卡斯,是的,我确实在我的第一个代码尝试',',但因为它不检测我的CVS文件中每行的行尾,所以我试着让它''..但它似乎仍然失败。 –

+1

'm(i,j)= * j;'这是不正确的。 – 5gon12eder

回答

-2

这将从正确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或等值转换因此。

+0

我试过了你的代码,我理解你的评论。它似乎仍然基于cvs文件工作。不知道这里出了什么问题。我只想让它可以计算每行1001列并读取3行。 –

+1

什么? @ D_9268 –

+0

也许我应该再次检查一遍。因为第二个while循环实际上循环了cvs文件中所有的3行数据,我可以通过事件来识别它们的每一行。这使我仍然感到困惑。 –

0

请随意将CSV文件读入vector <vector>(例如Lucas的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(); 
+0

为什么要构建'std :: vector'并且不直接将值存储在'Eigen :: Matrix'中? – 5gon12eder

+0

@ 5gon12eder如果在读取整个文件之前无法确定矩阵的大小,则更容易使用push_back并让容器处理大小调整。 –

+0

好吧,我以为你建议创建一个'std :: vector ',然后是'std :: vector ',最后是'Eigen :: MatrixXd'。两步过程似乎没问题。 – 5gon12eder

10

这里是你实际上可以复制的东西 - 粘贴

编写自己的 “语法分析器”

优点:重量轻,可定制

缺点:定制

#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"); 

使用犰狳库的解析器

优点:支持其他格式的,而不仅仅是以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); 
} 
+0

如果我们知道矩阵的大小,该怎么办? – Akshay

+1

@akshay:已更新 – user357269

相关问题