2015-12-13 45 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

相關問題