How to convert an xarray to std::vector?
Asked Answered
S

2

7

The docs make it quite clear on how to adapt a std::vector to a tensor object. https://xtensor.readthedocs.io/en/latest/adaptor.html

std::vector<double> v = {1., 2., 3., 4., 5., 6. };
std::vector<std::size_t> shape = { 2, 3 };
auto a1 = xt::adapt(v, shape);

But how can you do it for the other way round?

xt::xarray<double> a2 = { { 1., 2., 3.} };
std::vector<double> a2vector = ?;
Scent answered 4/4, 2020 at 15:23 Comment(0)
O
5

You can construct a std::vector from iterators. For your example:

std::vector<double> w(a1.begin(), a1.end());

The complete example then becomes:

#include <vector>
#include <xtensor/xadapt.hpp>
#include <xtensor/xio.hpp>

int main()
{
    std::vector<double> v = {1., 2., 3., 4., 5., 6.};
    std::vector<std::size_t> shape = {2, 3};
    auto a1 = xt::adapt(v, shape);
    std::vector<double> w(a1.begin(), a1.end());
    return 0;
}

References:

Okajima answered 5/4, 2020 at 11:4 Comment(0)
A
3

Unfortunately Tom de Geus' answer does not maintain dimensionality and hence transforms the xarray of shape {2, 3} into a vector of size 6. I stepped over this question, when attempting to construct a nested vector in order to plot a xarray with matplotlibcpp. For me it turned out, that Eigen::Matrix.. is a way more suitable class for this purpose. For the 2 dimensional case, one can comfortable convert the Eigen::Matrix to a nested std::vector. For higher dimensions, its worth to have a look here.

Code

transforms xt::xarray to Eigen::MatrixXf to nested std::vector

#include "xtensor/xarray.hpp"
#include "xtensor/xio.hpp"
#include <Eigen/Dense>



//https://mcmap.net/q/274021/-convert-eigen-matrix-to-c-array
Eigen::MatrixXf xarray_to_matrixXf(xt::xarray<float> arr)
{
      auto shape = arr.shape();
      int nrows = shape[0];
      int ncols = shape[1];

      Eigen::MatrixXf mat = Eigen::Map<Eigen::MatrixXf>(arr.data(), nrows, ncols);
      return mat;
}

// https://mcmap.net/q/1621810/-converting-eigen-matrixxf-to-2d-std-vector
std::vector<std::vector<float>> matrixXf2d_to_vector(Eigen::MatrixXf mat)
{
      std::vector<std::vector<float>> vec;

      for (int i=0; i<mat.rows(); ++i)
      {
          const float* begin = &mat.row(i).data()[0];
          vec.push_back(std::vector<float>(begin, begin+mat.cols()));
      }
      return vec;
}

// print a vector
// https://mcmap.net/q/1621811/-pretty-printing-nested-vectors
template<typename T1>
std::ostream& operator <<( std::ostream& out, const std::vector<T1>& object )
{
      out << "[";
      if ( !object.empty() )
      {
          for(typename std::vector<T1>::const_iterator
              iter = object.begin();
              iter != --object.end();
              ++iter) {
                  out << *iter << ", ";
          }
          out << *--object.end();
      }
      out << "]";
      return out;
}


int main()
{
      xt::xarray<float> xArr {{nan(""), 9}, {5, -6}, {1, 77}};
      std::cout << "xt::xarray<float> xArr = \n" << xArr << std::endl;


      Eigen::MatrixXf eigMat = xarray_to_matrixXf(xArr);
      std::cout << "Eigen::MatrixXf eigMat = \n" << eigMat << std::endl;

      std::vector<std::vector<float>> vec = matrixXf2d_to_vector(eigMat);
      std::cout << "std::vector<std::vector<float>> vec = " << vec << std::endl;

      return 0;
}

Output

xt::xarray<float> xArr = 
{{nan.,   9.},
 {  5.,  -6.},
 {  1.,  77.}}
Eigen::MatrixXf eigMat = 
nan  -6
  9   1
  5  77
std::vector<std::vector<float>> vec = [[nan, 9], [9, 5], [5, -6]]
Antarctica answered 24/6, 2020 at 14:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.