6

いくつかのゼロ行を含むマトリックスがあります。ゼロ行を削除したいと思います。行列は Nx3 です。私がやったことは簡単です。3 つの要素ごとに行を表すものを作成std::vectorし、それを に変換しEigen::MatrixXdます。ゼロ行を削除するエレガントな方法はありますか?

#include <iostream>
#include <vector>
#include <Eigen/Dense>



Eigen::MatrixXd VecToMat(const std::vector<double> vec)
{
    int rows(vec.size()/3) , cols(3);
    Eigen::MatrixXd temp( rows , cols);
    int count(0);
    for ( int i(0); i < rows; ++i)
    {
        temp(i,0) = vec[count]; 
        temp(i,1) = vec[count+1]; 
        temp(i,2) = vec[count+2]; 
        count += 3;
    }

    return temp;
}

Eigen::MatrixXd  getNewMat(Eigen::MatrixXd& Z)
{
    std::vector<double> vec;

    for ( int i(0); i < Z.rows(); ++i)
    {
        if ( (Z(i,0) && Z(i,1) && Z(i,2)) != 0 ){
            vec.push_back(Z(i,0));
            vec.push_back(Z(i,1));
            vec.push_back(Z(i,2));
        }
    }

    Eigen::MatrixXd temp = VecToMat(vec);

    return temp;
}

int main()
{
    Eigen::MatrixXd Z(5,3);
    Z.setOnes();


    Z(0,0) = 0;
    Z(0,1) = 0;
    Z(0,2) = 0;

    Z(1,0) = 0;
    Z(1,1) = 0;
    Z(1,2) = 0;

    Z(2,0) = 0;
    Z(2,1) = 0;
    Z(2,2) = 0;

    std::cout << Z << std::endl << std::endl;
    std::cout << getNewMat(Z) << std::endl;
    std::cin.get();
    return 0;
}
4

3 に答える 3

6

これは、私が非常にエレガントだと思う完全な実装です。これはゼロ以外のルールの順序を保持しないことに注意してください。これはおそらくあなたが望むものではありませんが、複雑さとコード行の両方でより効率的です:

void removeZeroRows(Eigen::MatrixXd& mat)
{
  Matrix<bool, Dynamic, 1> empty = (mat.array() == 0).rowwise().all();

  size_t last = mat.rows() - 1;
  for (size_t i = 0; i < last + 1;)
  {
    if (empty(i))
    {
      mat.row(i).swap(mat.row(last));
      empty.segment<1>(i).swap(empty.segment<1>(last));
      --last;
    }
    else
      ++i;
  }
  mat.conservativeResize(last + 1, mat.cols());
}
于 2014-12-08T18:14:40.543 に答える
0

空でない各行をベクトルに保存し、新しい行列を作成します

vector<block> buffer; //not sure of the type name for the rows
VectorXd zero(3); //or appropriate comparable type
for(int i = 0; i < Z.rows(); i++){ //note: possibly a function call each time
    if(Z.row(i) != zero)
    //if((Z.row(i) != 0).any()) //broadcasting comparison?
        buffer.push_back(Z.row(i));
}
MatrixXd return_value(buffer.size(), 3);
for(int i = buffer.size(); i --> 0;)
    return_value.row(i) = buffer[i];

return return_value;

警告: 新しいものを作成する代わりに古いもののサイズを変更すると、保存する前に内容が消去される場合があります。

ここからドキュメントを読むことができないので、ブロック オブジェクトに対してどのような種類の比較操作を実行できるかを自分で確認する必要があります。最後の結果として、row.any()(速い?) またはを試してくださいrow.squaredNorm() == 0

于 2014-08-04T09:26:28.073 に答える
0

基本的に、次のような疑似コードに従うことができます。

  • N = 行、M = 列を取得
  • Nごとに繰り返す
  • N[0] = 0 の場合、最初の非ゼロで終了する行を反復します
  • N[0] = 0 の場合 && .. && N[M] = 0
  • 行を削除

単一の行を削除する場合:

void removeRow(Eigen::MatrixXd& matrix, unsigned int rowToRemove) {
    unsigned int numRows = matrix.rows() - 1;
    unsigned int numCols = matrix.cols();
    unsigned int rowPos = numRows - rowToRemove;
    if( rowToRemove < numRows ) {
        matrix.block(rowToRemove, 0, rowPos, numCols) = matrix.block(rowToRemove + 1, 0, rowPos,numCols);
    }
    matrix.conservativeResize(numRows, numCols);
}
于 2014-08-04T08:55:00.667 に答える