Eigen3根据列条件选择行

时间:2019-10-12 03:11:46

标签: c++ eigen eigen3

我在本征中有一个二维的矩阵,例如:

<ip 1> - - [11/Oct/2019:12:00:24 -0600] "POST /xml_parse/ HTTP/1.1" 406 226 "-" "-" www.certainplace.com <ip 2>

当最后一列的值大于0.3时,我想选择所有行(或获取其行索引)。

我知道我可以通过迭代所有行并判断最后一个元素来执行此操作,但是我可能有10000行,要执行此操作,迭代将非常慢。

还有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

您可以尝试使用列而不是行,并将最后一列与矢量[n x 1]的0.3比较

答案 1 :(得分:1)

通过将最后一列中所有元素的比较结果存储到一个布尔数组中,可以在一行中完成相关行的选择,该布尔数组可以转换为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开发分支)

Eigen的开发分支提供了MatrixX构造函数的新重载,该重载允许直接给定矩阵的子集。

MatrixXd mat_sel = mat(keep_rows, keep_cols); 

应保留的列和行存储在Eigen::VectorXistd::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