Eigen3 select 根据列条件列出
Eigen3 select rows out based on column conditions
我有一个特征矩阵,它是二维的,例如:
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 时,我想要 select 所有行(或获取它的行索引)。
我知道我可以通过迭代所有行并判断最后一个元素来做到这一点,但我可能有 10000 行,这样做,迭代会很慢。
有更好的方法吗?
您可以尝试使用列而不是行,并将最后一列与向量 [n x 1] 的 0.3
进行比较
相关行的选择可以在一行中完成,方法是将最后一列中所有元素的比较结果存储到一个布尔数组中,该数组可以转换为一个 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::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;
}
我有一个特征矩阵,它是二维的,例如:
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 时,我想要 select 所有行(或获取它的行索引)。
我知道我可以通过迭代所有行并判断最后一个元素来做到这一点,但我可能有 10000 行,这样做,迭代会很慢。
有更好的方法吗?
您可以尝试使用列而不是行,并将最后一列与向量 [n x 1] 的 0.3
进行比较相关行的选择可以在一行中完成,方法是将最后一列中所有元素的比较结果存储到一个布尔数组中,该数组可以转换为一个 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::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;
}