Могу ли я изменить строку на месте с помощью Rcpp? - PullRequest
2 голосов
/ 03 октября 2019

Скажем, я бы хотел увеличить первую строку матрицы на единицу. Очевидный подход - A.row(0) = A.row(0) + 1;, но он создает новую строку вместо изменения существующей и может вызвать некоторые проблемы с производительностью при большой матрице.

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

library(Rcpp)
cppFunction('
void increaseFirstRow(NumericMatrix& A) {
    NumericVector B = A.row(0);
    B = B + 1;
}')
A <- diag(c(1.0, 2.0, 3.0))
increaseFirstRow(A)

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

> A
     [,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    2    0
[3,]    0    0    3

Ответы [ 2 ]

2 голосов
/ 03 октября 2019

По приведенной выше формулировке, я думаю, вы хотели получить ссылку на конкретные части матрицы. Следующая матрица работает с типами матриц:

*Matrix::Row = x( 0 , Rcpp::_);  // first row
*Matrix::Column = x( Rcpp::_ , 0); // first column
*Matrix::Sub = x( Rcpp::Range(0, 1) , Rcpp::Range(2, 3)); // first 2 rows and 3 -4th column.

В вашем случае это будет:

#include <Rcpp.h>

// [[Rcpp::export]]
void row_ref(Rcpp::NumericMatrix M) {
    // Create a reference to the 1st row in M.
    Rcpp::NumericMatrix::Row x = M.row(0);
    // Increase the first row in M.
    x = x + 10; 
}

Пример:

(A <- diag(c(1.0, 2.0, 3.0)))
#      [,1] [,2] [,3]
# [1,]    1    0    0
# [2,]    0    2    0
# [3,]    0    0    3

row_ref(A)

A
#      [,1] [,2] [,3]
# [1,]   11   10   10
# [2,]    0    2    0
# [3,]    0    0    3
2 голосов
/ 03 октября 2019

Вот простое решение в RcppArmadillo и, после редактирования, в самом Rcpp:

Код с примером

#include <RcppArmadillo.h>

// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
void incRow(arma::mat& M) {
  M.row(0) = M.row(0) + 1;
}

// [[Rcpp::export]]
void incRow2(Rcpp::NumericMatrix M) {
  M(0,Rcpp::_) = M(0,Rcpp::_) + 1;
}


/*** R
A <- diag(c(1.0, 2.0, 3.0))
incRow(A)
A
incRow2(A)
A
*/

Вывод

R> Rcpp::sourceCpp("/tmp/armarow.cpp")

R> A <- diag(c(1.0, 2.0, 3.0))

R> incRow(A)

R> A
     [,1] [,2] [,3]
[1,]    2    1    1
[2,]    0    2    0
[3,]    0    0    3

R> incRow2(A)

R> A
     [,1] [,2] [,3]
[1,]    3    2    2
[2,]    0    2    0
[3,]    0    0    3
R> 
...