Eigen boolean array slicing
As pointed out in the answer to an similar question here: Submatrices and indices using Eigen, libigl adds this functionality to Eigen.
igl::slice(A,indices,B);
Is equivalent to
B = A(indices)
Eigen3 select rows out based on column conditions
The selection of the relevant rows can be done in a single line, by storing the result of the comparison of all the elements in the last column into a boolean array, which can be cast into a VectorXi.
VectorXi is_selected = (mat.col(last_col).array() > 0.3).cast<int>();
This information can then be used to prepare a new matrix which contains only the selected rows. An entire code using this method is shown below.
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
int main() {
const int nr = 10;
const int nc = 5;
MatrixXd mat = MatrixXd::Random(nr,nc);
std::cout << "original:\n" << mat << std::endl;
int last_col = mat.cols() - 1;
VectorXi is_selected = (mat.col(last_col).array() > 0.3).cast<int>();
MatrixXd mat_sel(is_selected.sum(), mat.cols());
int rownew = 0;
for (int i = 0; i < mat.rows(); ++i) {
if (is_selected[i]) {
mat_sel.row(rownew) = mat.row(i);
rownew++;
}
}
std::cout << "selected:\n" << mat_sel << std::endl;
}
Demo: https://godbolt.org/z/f0_fC0
Edit: Using new feature (Eigen 3.4 or 3.3.90 development branch)
The development branch of Eigen provides a new overload of the MatrixX constructor that allows for the direct subsetting of a given matrix.
MatrixXd mat_sel = mat(keep_rows, keep_cols);
The columns and rows that should be kept are stored in an Eigen::VectorXi
or in a std::vector<int>
:
#include <Eigen/Dense>
#include <iostream>
#include <vector>
using namespace Eigen;
int main() {
MatrixXd mat = MatrixXd::Random(10,5);
std::cout << "original:\n" << mat << std::endl;
std::vector<int> keep_rows;
for (int i = 0; i < mat.rows(); ++i) {
if (mat(i,mat.cols() - 1) > 0.3) {
keep_rows.push_back(i);
}
}
VectorXi keep_cols = VectorXi::LinSpaced(mat.cols(), 0, mat.cols());
MatrixXd mat_sel = mat(keep_rows, keep_cols);
std::cout << "selected:\n" << mat_sel << std::endl;
}
Demo: https://godbolt.org/z/Ag7g7f
Is there a better way to implement matlab's Logical Indexing using Eigen/C++?
This is an old one but....Eigen 3.4 makes it way cleaner to do this. Sadly I can't speak to the performance. I'm mainly interested readability. I made this:
class logical
{
private:
const Index new_size;
Array<Index, Dynamic, 1> old_inds;
public:
logical(const Array<bool, Dynamic, 1> &keep) : new_size(keep.count()), old_inds(new_size)
{
for (Index i = 0, j = 0; i < keep.size(); i++)
if (keep(i))
old_inds(j++) = i;
}
Index size() const { return new_size; }
Index operator[](Index new_ind) const { return old_inds(new_ind); }
};
Which is used like:
logical inds(ind_to_keep);
Y_slice = Y(inds); // vector
H_slice = H(inds, all); // remove some rows
R_slice = R(inds, inds); // remove the same rows as columns
Eigen help is at the bottom of this page:
https://eigen.tuxfamily.org/dox-devel/group__TutorialSlicingIndexing.html
Eigen: select function on complex matrix
As in the example you linked to, you need to compare the .array()
(.real()
?) to > 1e-8
and use Eigens functions (or unaryExpr
) to manipulate the values of the matrix:
v = (v.array().real()
// ^^^
// can't compare complex numbers
> 1e-8)
// ^^^
// Actually compare the number
.select(v.cwiseSqrt().cwiseInverse(), v);
// ^^^
// Use Eigens functions or alternatively unaryExpr
// In one line:
v = (v.array().real() > 1e-8).select(v.cwiseSqrt().cwiseInverse(), v);
Submatrices and indices using Eigen
There currently is a feature request for selecting sub-matrices by indexing filed at the Eigen BugTracker system. Therefore, I doubt it will be possible that way.
The only workaround I could think of is to copy the data manually. Not very nice though.
Related Topics
Copy Constructor of Derived Qt Class
C and C++ Functions Without a Return Statement
a Few Things About Division by Zero in C
Returning VS. Using a Reference Parameter
How to Know If Std::Map Insert Succeeded or Failed
How Could I Sensibly Overload Placement Operator New
Absence of Typeof Operator in C++03
Best C++ Development Environment in Linux
Locating iOStream in Clang++: Fatal Error: 'iOStream' File Not Found
Cross-Platform C++: Use The Native String Encoding or Standardise Across Platforms
Volatile Struct = Struct Not Possible, Why
How to Resize an Image to a Specific Size in Opencv
Mbcs Error Building Mfc C++ Project with Visual Studio
How to Add Code at the Entry of Every Function
How to Check If a File Is Still Being Written