Home > Mobile >  Convert every column of an Eigen::Matrix to an std::vector?
Convert every column of an Eigen::Matrix to an std::vector?

Time:10-29

Lets assume I have the following Eigen::Matrix:

  Eigen::MatrixXf mat(3, 4);
  mat   <<  1.1, 2, 3, 50,
            2.2, 2, 3, 50,
            3.1, 2, 3, 50;

Now how can I convert every column into an std::vector<float> I tried an adaptation of this solution typecasting Eigen::VectorXd to std::vector:

  std::vector<float> vec;
  vec.resize(mat.rows());
  for(int col=0; col<mat.cols(); col  ){
     Eigen::MatrixXf::Map(&vec[0], mat.rows());
  }

But that throws the following error:

n template: static_assert failed due to requirement 'Map<Eigen::Matrix<float, -1, -1, 0, -1, -1>, 0, Eigen::Stride<0, 0>>::IsVectorAtCompileTime' "YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX"

What is the right and most efficient solution?

CodePudding user response:

The below program shows how you can extract the first column from Eigen::Matrix into a std::vector<float> .

Version 1: Extract only a single column at a time

int main()
{
 

Eigen::MatrixXf mat(3, 4);
  mat   <<  1.1, 2, 3, 50,
            2.2, 2, 3, 50,
            3.1, 2, 3, 50;
  

  std::vector<float> column1(mat.rows());

  
  for(int j = 0; j < mat.rows();   j)
  {
    column1.at(j) = mat(j, 0);//this will put all the elements in the first column of Eigen::Matrix into the column3 vector
  }
  for(float elem: column1)
  {
    std::cout<<elem<<std::endl;
  }

  //similarly you can create columns corresponding to other columns of the Matrix. Note that you can also 
  //create std::vector<std::vector<float>> for storing all the rows and columns as shown in version 2 of my answer
return 0;
}

The output of version 1 is as follows:

1.1
2.2
3.1

Similarly you can extract other columns.

Note that if you want to extract all columns then you can create/use a std::vector<std::vector<float>> where you can store all the rows and columns as shown below:

Version 2: Extract all columns into a 2D std::vector

int main()
{
 

Eigen::MatrixXf mat(3, 4);
  mat   <<  1.1, 2, 3, 50,
            2.2, 2, 3, 50,
            3.1, 2, 3, 50;
  

std::vector<std::vector<float>> vec_2d(mat.rows(), std::vector<float>(mat.cols(), 0));  

for(int col = 0; col < mat.cols();   col)
{
    for(int row = 0; row < mat.rows();   row)
    {
        
        vec_2d.at(row).at(col) = mat(row, col);
        
    }
    
}

//lets print out i.e., confirm if our vec_2d contains the columns correctly
for(int col = 0; col < mat.cols();   col)
{   std::cout<<"This is the "<<col 1<< " column"<<std::endl;
    for(int row = 0; row < mat.rows();   row)
    {
        
        std::cout<<vec_2d.at(row).at(col)<<std::endl;
        
    }   
}
  
return 0;
}

The output of version 2 is as follows:

This is the 1 column
1.1
2.2
3.1
This is the 2 column
2
2
2
This is the 3 column
3
3
3
This is the 4 column
50
50
50

CodePudding user response:

I think the most elegant Solution would be to use Eigen::Map. In your case you would do it like this:

 Eigen::MatrixXf mat(3, 4);
  mat   <<  1.1, 2, 3, 50,
            2.2, 2, 3, 50,
            3.1, 2, 3, 50;

  std::vector<float> vec;
  vec.resize(mat.rows());
  for(int col=0; col<mat.cols(); col  ){
    Eigen::Map<Eigen::MatrixXf>(vec.data(), mat.rows(), 1 ) = mat.col(col); }
  • Related