Eigen3 выбрать строки на основе условий столбца - PullRequest
0 голосов
/ 12 октября 2019

У меня есть собственная матрица, которая имеет 2 измерения, например:

122 443 544 456 0.9
324 435 5465 645 0.8
32 434 545 546 0.778
435 546 6565 656 0.6878
546 6565 656 3453 54 0.7788
5456 546 545 6565 3434 0.244
435 5456 656 656 6565 0.445
.....

Я хочу выбрать все строки (или получить его индекс строки), когда значение последнего столбца больше 0,3.

Я знаю, что могу сделать это путем итерации всех строк и оценить последний элемент, но у меня может быть 10000 строк, для этого итерация будет очень медленной.

Есть ли лучший способ сделать это? это?

Ответы [ 2 ]

1 голос
/ 12 октября 2019

Выбор соответствующих строк может быть сделан в одной строке путем сохранения результата сравнения всех элементов в последнем столбце в логический массив, который может быть преобразован в VectorXi.

VectorXi is_selected = (mat.col(last_col).array() > 0.3).cast<int>();

Эта информация может затем использоваться для подготовки новой матрицы, которая содержит только выбранные строки. Весь код, использующий этот метод, показан ниже.

#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;
}

Демонстрация: https://godbolt.org/z/f0_fC0

Редактировать: Использование новой функции (ветка разработки Eigen 3.4 или 3.3.90)

Ветвь разработкиof Eigen обеспечивает новую перегрузку конструктора MatrixX, которая допускает прямое подмножество данной матрицы.

MatrixXd mat_sel = mat(keep_rows, keep_cols); 

Столбцы и строки, которые следует сохранить, хранятся в Eigen::VectorXi или в 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; 
}

Демо: https://godbolt.org/z/Ag7g7f

1 голос
/ 12 октября 2019

Вы можете попробовать использовать столбец вместо строки и сравнить последний столбец с вектором [nx 1] 0,3

...