如何使用Rcpp缩放NumericMatrix?

nal*_*zok 2 c++ r matrix syntactic-sugar rcpp

这就是我现在正在做的

library(Rcpp)

A <- diag(c(1.0, 2.0, 3.0))
rownames(A) <- c('X', 'Y', 'Z')
colnames(A) <- c('A', 'B', 'C')

cppFunction('
void scaleMatrix(NumericMatrix& A, double x) {
    A = A * x;
}')
Run Code Online (Sandbox Code Playgroud)

不幸的是,它不起作用:(

> A
  A B C
X 1 0 0
Y 0 2 0
Z 0 0 3
> scaleMatrix(A, 2)
> A
  A B C
X 1 0 0
Y 0 2 0
Z 0 0 3
Run Code Online (Sandbox Code Playgroud)

我从Rcpp常见问题解答5.1中获悉,Rcpp应该能够更改按值传递的对象。从Dirk回答我以前的问题中窃取一个例子:

> library(Rcpp)
> cppFunction("void inplaceMod(NumericVector x) { x = x * 2; }")
> x <- as.numeric(1:5)
> inplaceMod(x)
> x
[1]  2  4  6  8 10
Run Code Online (Sandbox Code Playgroud)

我很困惑:可以NumericVector就地修改,但不能修改NumericMatrix

Ral*_*ner 6

您可以使用NumericVector而不是来保留行和列的名称NumericMatrix,请记住,R中的矩阵只是具有附加维的向量。您可以在从R转到C ++时(scaleVector以下)或在C ++内(scaleMatrix以下来自@Roland现在删除的答案)进行此切换

library(Rcpp)
cppFunction('
NumericVector scaleVector(NumericVector& A, double x) {
    A = A * x;
    return A;
}')

cppFunction('
NumericMatrix scaleMatrix(NumericMatrix& A, double x) {
    NumericVector B = A;
    B = B * x;
    return A;
}')
Run Code Online (Sandbox Code Playgroud)

如果将这两个函数应用于矩阵,则保留行名和列名。但是,矩阵未更改到位:

A <- diag(1:3)
rownames(A) <- c('X', 'Y', 'Z')
colnames(A) <- c('A', 'B', 'C')

scaleMatrix(A, 2)
#>   A B C
#> X 2 0 0
#> Y 0 4 0
#> Z 0 0 6
scaleVector(A, 2)
#>   A B C
#> X 2 0 0
#> Y 0 4 0
#> Z 0 0 6
A
#>   A B C
#> X 1 0 0
#> Y 0 2 0
#> Z 0 0 3
Run Code Online (Sandbox Code Playgroud)

原因diag(1:3)是实际上是一个整数矩阵,因此在将其转移到数字矩阵(或向量)时会生成一个副本:

is.integer(A)
#> [1] TRUE
Run Code Online (Sandbox Code Playgroud)

如果使用数字矩阵作为开始,则会进行适当的修改:

A <- diag(c(1.0, 2.0, 3.0))
rownames(A) <- c('X', 'Y', 'Z')
colnames(A) <- c('A', 'B', 'C')

scaleMatrix(A, 2)
#>   A B C
#> X 2 0 0
#> Y 0 4 0
#> Z 0 0 6
scaleVector(A, 2)
#>   A B  C
#> X 4 0  0
#> Y 0 8  0
#> Z 0 0 12
A
#>   A B  C
#> X 4 0  0
#> Y 0 8  0
#> Z 0 0 12
Run Code Online (Sandbox Code Playgroud)

  • @nalzok我删除了这样做的答案,但是您可以执行`NumericVector B = A;`并修改`B`。如果还将在适当的地方修改“ A”(因为“ A”在内部是矢量)。 (3认同)