Как удалить определенную строку или столбец при использовании Eigen Library c++

Я использую библиотеку Eigen для своего проекта. Я ищу, как удалить определенную строку или столбец из данной матрицы в Eigen. Я не успешен.

MatrixXd A = X1 X2 X3 X4
             Y1 Y2 Y3 Y4
             Z1 Z2 Z3 Z4
             A1 A2 A3 A4
MatrixXd Atransform = X1 X2 X4
                      Y1 Y2 Y4
                      Z1 Z2 Z4
                      A1 A2 A4
enter code here

кроме перебора всей матрицы или использования блочных операций над матрицей A . Есть ли способ сделать это просто.


person wholock    schedule 08.11.2012    source источник
comment
Я не думаю, что есть другой метод, кроме использования блочных операций.   -  person Jakob    schedule 14.11.2012


Ответы (7)


Использование блочных функций немного чище:

void removeRow(Eigen::MatrixXd& matrix, unsigned int rowToRemove)
{
    unsigned int numRows = matrix.rows()-1;
    unsigned int numCols = matrix.cols();

    if( rowToRemove < numRows )
        matrix.block(rowToRemove,0,numRows-rowToRemove,numCols) = matrix.block(rowToRemove+1,0,numRows-rowToRemove,numCols);

    matrix.conservativeResize(numRows,numCols);
}

void removeColumn(Eigen::MatrixXd& matrix, unsigned int colToRemove)
{
    unsigned int numRows = matrix.rows();
    unsigned int numCols = matrix.cols()-1;

    if( colToRemove < numCols )
        matrix.block(0,colToRemove,numRows,numCols-colToRemove) = matrix.block(0,colToRemove+1,numRows,numCols-colToRemove);

    matrix.conservativeResize(numRows,numCols);
}
person Andrew    schedule 11.01.2014
comment
Обычно это должно работать, но не гарантируется, что Eigen будет копировать блоки слева направо (или сверху вниз), поэтому теоретически вы можете столкнуться с проблемами алиасинга. - person chtz; 30.12.2016
comment
@chtz: чтобы избежать этой проблемы, используйте функцию .eval(). - person davidhigh; 26.04.2017

Вы можете сделать это намного проще и короче, используя Eigen 3.3.0+ (выпущено в 2016.08):

vector<int> indicesToKeep = vector<int>{ 1, 2, 3 };
VectorXi indicesToKeepVector = VectorXi(indicesToKeep.data(), indicesToKeep.size());
MatrixXf matrix = MatrixXf(); // your data should be here!
matrix = matrix(Eigen::placeholders::all, indicesToKeepVector); // select columns you want to keep(indicesToKeep), discard others
matrix = matrix(indicesToKeepVector, Eigen::placeholders::all); // select rows you want to keep(indicesToKeep), discard others
matrix = matrix(Eigen::seq(5, 10), Eigen::placeholders::all); // keep rows from 5 to 10
matrix = matrix(Eigen::placeholders::all, Eigen::seq(5, 10)); // keep columns from 5 to 10
matrix = matrix(Eigen::seqN(5, 5), Eigen::placeholders::all); // keep rows from 5 to 10
matrix = matrix(Eigen::placeholders::all, Eigen::seqN(5, 5)); // keep columns from 5 to 10
person flatronka    schedule 17.01.2019

Чтобы улучшить ответ Эндрю, используйте bottomRows/rightCols.

void removeRow(Eigen::MatrixXd& matrix, unsigned int rowToRemove)
{
    unsigned int numRows = matrix.rows()-1;
    unsigned int numCols = matrix.cols();

    if( rowToRemove < numRows )
        matrix.block(rowToRemove,0,numRows-rowToRemove,numCols) = matrix.bottomRows(numRows-rowToRemove);

    matrix.conservativeResize(numRows,numCols);
}

void removeColumn(Eigen::MatrixXd& matrix, unsigned int colToRemove)
{
    unsigned int numRows = matrix.rows();
    unsigned int numCols = matrix.cols()-1;

    if( colToRemove < numCols )
        matrix.block(0,colToRemove,numRows,numCols-colToRemove) = matrix.rightCols(numCols-colToRemove);

    matrix.conservativeResize(numRows,numCols);
}
person raahlb    schedule 19.09.2017

Вы можете найти следующую статическую версию лучше для определенных целей (и более соответствующую духу эффективности времени компиляции Eigen). В этом случае вы будете создавать новую матрицу без строки. Аналогичная функция может быть построена для столбцов с использованием .leftCols() .rightCols()

template<typename T>
inline constexpr auto removeRow(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& matrix, const int& rowNum)
{
    return (Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>(matrix.rows() - 1, matrix.cols())
        << static_cast<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>>(matrix.topRows(rowNum - 1)),
        static_cast<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>>(matrix.bottomRows(matrix.rows() - rowNum))).finished();
}

Наслаждаться!

person AOK    schedule 23.11.2017

Я знаю, что это старый вопрос, но кажется, что Eigen теперь поддерживает создание подматрицы, определяемой проиндексированными строками и столбцами: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=329 http://eigen.tuxfamily.org/dox-devel/classEigen_1_1DenseBase.html#a0b44220621cd59a75cd0f48cc499518f

Просто в документации вроде нет...

person NaN    schedule 05.04.2018

Я очень новичок в С++, но этот код работает в майском приложении.

Он работает только для полных динамических матриц, но может адаптироваться.

Если у кого-то есть лучший способ, пожалуйста, покажите мне, я действительно хочу учиться.

template<typename ScalarType>
void MatrixXdRemoveCol(Eigen::Matrix<ScalarType,-1,-1,0,-1,-1> *mat, int colindex)
{
    Eigen::Matrix<ScalarType,-1,-1,0,-1,-1> *auxmat = new Eigen::Matrix<ScalarType,-1,-1,0,-1,-1>;

    *auxmat = *mat;

    mat->resize(mat->rows(),mat->cols()-1);

    int rightColsSize = auxmat->cols()-colindex-1;

    mat->leftCols(colindex) = auxmat->leftCols(colindex);
    mat->rightCols(rightColsSize) = auxmat->rightCols(rightColsSize);
}

template<typename ScalarType>
void MatrixXdRemoveCols(Eigen::Matrix<ScalarType,-1,-1,0,-1,-1> *mat, std::vector<int>* cols)
{
    for(auto iter = cols->rbegin();iter != cols->rend();iter++)
        MatrixXdRemoveCol<ScalarType>(mat,*iter);
}

template<typename ScalarType>
void MatrixXdRemoveRow(Eigen::Matrix<ScalarType,-1,-1,0,-1,-1> *mat, int rowindex)
{
    Eigen::Matrix<ScalarType,-1,-1,0,-1,-1> *auxmat = new Eigen::Matrix<ScalarType,-1,-1,0,-1,-1>;

    *auxmat = *mat;

    mat->resize(mat->rows()-1,mat->cols());

    int BottomRowsSize = auxmat->rows()-rowindex-1;

    mat->topRows(rowindex) = auxmat->topRows(rowindex);
    mat->bottomRows(BottomRowsSize) = auxmat->bottomRows(BottomRowsSize);
}
person Marcos Paulo SUS    schedule 11.01.2013
comment
Я не знаком с библиотекой eigen, но с общей точки зрения С++ похоже, что у вас есть утечки памяти в ваших функциях: вы выделяете auxmats, но не удаляете их. - person cybevnm; 12.01.2014
comment
Как правило, вам следует избегать new при написании C++ -- если только вам это действительно не нужно и вы не знаете, что делаете. Вместо этого просто напишите Eigen::Matrix<ScalarType,-1,-1,0,-1,-1> auxmat = mat (и передайте mat по ссылке, а не по указателю) - person chtz; 30.12.2016

person    schedule
comment
Из отзыва: Привет, пожалуйста, не отвечайте только исходным кодом. Постарайтесь дать хорошее описание того, как работает ваше решение. См.: Как написать хороший ответ?. Спасибо - person sɐunıɔןɐqɐp; 22.01.2020