第 9 章 Matrix类
9.1 创建矩阵对象
矩阵对象可由如下几种方式创建。
// 创建一个矩阵对象,等价于在R语句
// m <- matrix(0, nrow=2, ncol=2)
NumericMatrix m1( 2 );
// m <- matrix(0, nrow=2, ncol=3)
NumericMatrix m2( 2 , 3 );
// m <- matrix(v, nrow=2, ncol=3)
NumericMatrix m3( 2 , 3 , v.begin() );
此外,R中的矩阵对象,实际上是行数和列数在属性dim
中设定好的向量。因此,如果你在Rcpp中,创建一个有dim
属性的向量,并且将其作为返回值传递给R,那么该向量在R中会被作为矩阵对待。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
NumericVector rcpp_matrix(){
// 创建一个向量对象
NumericVector v = {1,2,3,4};
// 设置该对象的`dim`属性
v.attr("dim") = Dimension(2, 2);
// 返回该对象给R
return v;
}
需要注意的是,c++98是不允许直接使用v = {1,2,3,4}
来赋值的,因此,需要加上 // [[Rcpp::plugins(cpp11)]]
,确保能使用C++11的新特性。
执行结果:
然而,即便你给某个向量对象的dim
属性赋值,在Rcpp中对象的类型还是为向量类。因此,如果你希望在Rcpp中,将其转化为矩阵类,你需要使用 as<T>()
函数。
9.2 访问矩阵元素
通过使用()
符号,你可以指定行,列号来获取,分配矩阵对象的元素值。和在向量中的索引类似,矩阵中的行与列号也是从0开始。如果你希望获取某一行或者一列,使用_
符号。也可以使用[]
操作符,来访问矩阵元素(将矩阵理解为按列连接的向量)。
// 创建一个5*5的矩阵
NumericMatrix m( 5, 5 );
// 检索0行,2列的元素,即第一行,第三列的元素
double x = m( 0 , 2 );
// 将0行(向量)赋给v
NumericVector v = m( 0 , _ );
// 将2列赋给v
NumericVector v = m( _ , 2 );
// 将矩阵m的0~1行,2~3列赋值给矩阵m2
NumericMatrix m2 = m( Range(0,1) , Range(2,3) );
// 按照向量的方式来检索矩阵元素
m[5]; // 指向m(0,1)的位置,即第6个元素(矩阵按列连接),为第1行,第2列元素,
9.2.1 访问行,列与子矩阵
Rcpp也提供了类型来进行矩阵特定部分的“引用”(references)。
NumericMatrix::Column col = m( _ , 1); // 对于列1的引用
NumericMatrix::Row row = m( 1 , _ ); // 对行1的引用
NumericMatrix::Sub sub = m( Range(0,1) , Range(2,3) ); //对子矩阵的引用
对这些“引用”对象的赋值,等效于直接修改其原始矩阵的对应部分。比如,对于上面例子中的col
对象进行赋值,会直接把m的列1的值进行对应的修改。
在test.cpp
文件中键入下面的代码。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix test(NumericMatrix v, int idx){
NumericMatrix::Column col = v( _, idx);
//将idx列的所有元素乘以2,v也会被修改
col = col * 2;
//上行代码等效于
//v( _, idx) = 2 * v( _, idx);
return v;
}
在R中的执行结果为:
> sourceCpp('test.cpp')
> a <- matrix(1:16,4,4)
> a
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
> test(a,1)
[,1] [,2] [,3] [,4]
[1,] 1 10 9 13
[2,] 2 12 10 14
[3,] 3 14 11 15
[4,] 4 16 12 16
可以看到,矩阵的第2列(Rcpp索引为1)已经变为原来的2倍。
9.3 成员函数
Since Matrix
is actually Vector
, Matrix
basically has the same member functions as Vector
. Thus, member functions unique to Matrix
are only presented below.
此前提到,Matrix
实际上也是Vector
,所以,Matrix
基本上与Vector
有着相同的成员函数。因此,在在此列出Matrix
自身独特的成员函数。
9.3.1 nrow() rows()
返回行数。
在test.cpp
文件中键入下面的代码。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
int test(NumericMatrix v){
return v.nrow();
}
在R中的执行结果为:
9.3.2 ncol() cols()
返回矩阵列数。
在test.cpp
文件中键入下面的代码。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
int test(NumericMatrix v){
return v.ncol();
}
在R中的执行结果为:
9.3.3 row( i )
返回矩阵 行i
的“引用”,关于“引用”的具体信息,可参考9.2.1。
在test.cpp
文件中键入下面的代码。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix test(NumericMatrix v){
v.row(1) = 2 * v.row(1);
return v;
}
在R中的执行结果为:
9.3.4 column( i )
返回矩阵 行i
列的“引用”
9.3.5 fill_diag( x )
使用x
填充矩阵对角线元素。
在test.cpp
文件中键入下面的代码。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix test(NumericMatrix v,double x){
v.fill_diag(x);
return v;
}
在R中的执行结果为:
9.3.6 offset( i, j )
返回i
行和j
列对应的元素,在将矩阵作为列向量连接时其对应的索引。
matrix中的offset函数是私有的,似乎因此导致调用失败。
9.4 静态成员函数
Matrix
基本上有着和Vector
相同的成员函数。其独特的成员函数在此处列出。
9.4.1 Matrix::diag( size, x )
返回一个矩阵,行列数均为size
,对角元素为x
。
在test.cpp
文件中键入下面的代码。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix test(int size, double x){
NumericMatrix v = NumericMatrix::diag(size,x);
return v;
}
在R中的执行结果为:
9.5 与Matrix相关的其他函数
此部分展示一些其他与矩阵相关的函数。
9.5.1 rownames( m )
获取和设定矩阵行名。
在test.cpp
文件中键入下面的代码。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix test(NumericMatrix v1, NumericMatrix v2){
CharacterVector v1_rname = rownames(v1);
rownames(v2) = v1_rname;
return v2;
}
在R中的执行结果为:
9.5.2 colnames( m )
获取和设定矩阵列名,方法同上。
CharacterVector ch = colnames(m);
colnames(m) = ch;
9.5.3 transpose( m )
返回矩阵m
的转置。
在test.cpp
文件中键入下面的代码。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix test(NumericMatrix v){
return transpose(v);
}
在R中的执行结果为: