如何读取 CSV 文件并分配给特征矩阵?
How to read CSV file and assign to Eigen Matrix?
我尝试将一个大的 cvs 文件读入本征矩阵,下面的代码发现有问题,它无法检测 cvs 文件中的每一行 \n 以在矩阵中创建多行。 (它用单行读取整个文件)。不确定代码有什么问题。有人可以在这里建议吗?
我也在寻找一种有效的方法来读取具有 10k 行和 1k 列的 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
这将从 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
或等同的转换,一旦您希望如此对待它们。
根据需要将 CSV 文件读入您的 vector < vector >
(例如 Lucas 的 )。代替 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();
这里有一些你可以实际复制粘贴的东西
自己写"parser"
优点:轻巧且可自定义
缺点:可定制
#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);
}
我尝试将一个大的 cvs 文件读入本征矩阵,下面的代码发现有问题,它无法检测 cvs 文件中的每一行 \n 以在矩阵中创建多行。 (它用单行读取整个文件)。不确定代码有什么问题。有人可以在这里建议吗? 我也在寻找一种有效的方法来读取具有 10k 行和 1k 列的 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
这将从 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
或等同的转换,一旦您希望如此对待它们。
根据需要将 CSV 文件读入您的 vector < vector >
(例如 Lucas 的 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();
这里有一些你可以实际复制粘贴的东西
自己写"parser"
优点:轻巧且可自定义
缺点:可定制
#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);
}