C中的R扩展,设置矩阵行/列名称

Nic*_*ick 6 c r matrix

我正在编写一个用C语言操作矩阵的R包.目前,返回R的矩阵包含行/列名称的数字.在C中修改对象时,我宁愿分配自己的行/列名称.

我用Google搜索了大约一个小时,但还没有找到一个好的解决方案.我发现的最接近的是dimnames,但我想命名每一列,而不仅仅是两个维度.矩阵大于4x4,下面只是我想要做的一个小例子.

行数是4 ^ x,其中X是行名称的长度

Current
     [,1] [,2] [,3] [,4]
[1,] 0.20 0.00 0.00 0.80
[2,] 0.25 0.25 0.25 0.25
[3,] 0.25 0.25 0.25 0.25
[4,] 1.00 0.00 0.00 0.00
[5,] 0.20 0.00 0.00 0.80
[6,] 0.25 0.25 0.25 0.25
[7,] 0.25 0.25 0.25 0.25
[8,] 1.00 0.00 0.00 0.00
[9,] 0.20 0.00 0.00 0.80
[10,] 0.25 0.25 0.25 0.25
[11,] 0.25 0.25 0.25 0.25
[12,] 1.00 0.00 0.00 0.00
[13,] 0.20 0.00 0.00 0.80
[14,] 0.25 0.25 0.25 0.25
[15,] 0.25 0.25 0.25 0.25
[16,] 1.00 0.00 0.00 0.00

Desired
     [A] [C] [G] [T]
 [AA] 0.20 0.00 0.00 0.80
 [AC] 0.25 0.25 0.25 0.25
 [AG] 0.25 0.25 0.25 0.25
 [AT] 1.00 0.00 0.00 0.00
 [CA] 0.20 0.00 0.00 0.80
 [CC] 0.25 0.25 0.25 0.25
 [CG] 0.25 0.25 0.25 0.25
 [CT] 1.00 0.00 0.00 0.00
 [GA] 0.20 0.00 0.00 0.80
 [GC] 0.25 0.25 0.25 0.25
 [GG] 0.25 0.25 0.25 0.25
 [GT] 1.00 0.00 0.00 0.00
 [TA] 0.20 0.00 0.00 0.80
 [TC] 0.25 0.25 0.25 0.25
 [TG] 0.25 0.25 0.25 0.25
 [TT] 1.00 0.00 0.00 0.00
Run Code Online (Sandbox Code Playgroud)

Dir*_*tel 6

如果您对C++而不是C开放,那么Rcpp可以使这更容易一些.我们只是像在R中一样创建一个包含行和列名的列表对象,并将其分配给dimnames矩阵对象的属性:

R> library(inline)                         # to compile, link, load the code here
R> src <- '
+   Rcpp::NumericMatrix x(2,2);
+   x.fill(42);                           // or more interesting values
+   // C++0x can assign a set of values to a vector, but we use older standard
+   Rcpp::CharacterVector rows(2); rows[0] = "aa"; rows[1] = "bb";
+   Rcpp::CharacterVector cols(2); cols[0] = "AA"; cols[1] = "BB";
+   // now create an object "dimnms" as a list with rows and cols
+   Rcpp::List dimnms = Rcpp::List::create(rows, cols);
+   // and assign it
+   x.attr("dimnames") = dimnms;
+   return(x);
+ '
R> fun <- cxxfunction(signature(), body=src, plugin="Rcpp")
R> fun()
   AA BB
aa 42 42
bb 42 42
R> 
Run Code Online (Sandbox Code Playgroud)

列和行名称的实际分配是如此手动...因为当前的C++标准不允许在初始化时直接分配向量,但这会改变.

编辑:我刚刚意识到我当然可以create()在行和colnames上使用静态方法,这使得它更容易和更短

R> src <- '
+   Rcpp::NumericMatrix x(2,2);
+   x.fill(42);                           // or more interesting values
+   Rcpp::List dimnms =                   // two vec. with static names
+       Rcpp::List::create(Rcpp::CharacterVector::create("cc", "dd"),
+                          Rcpp::CharacterVector::create("ee", "ff"));
+   // and assign it
+   x.attr("dimnames") = dimnms;
+   return(x);
+ '
R> fun <- cxxfunction(signature(), body=src, plugin="Rcpp")
R> fun()
   ee ff
cc 42 42
dd 42 42
R> 
Run Code Online (Sandbox Code Playgroud)

因此,我们可以使用PROTECT/UNPROTECT并且没有内存管理,只需要三到四个语句.


Jos*_*ich 5

正如吉姆所说,这在 R 中要容易得多。我通过参数将名称传递给 C 函数nam

#include <Rinternals.h>
SEXP myMat(SEXP nam) {
  /*PrintValue(nam);*/
  SEXP ans, dimnames;
  PROTECT(ans = allocMatrix(REALSXP, length(nam), length(nam)));
  PROTECT(dimnames = allocVector(VECSXP, 2));
  SET_VECTOR_ELT(dimnames, 0, nam);
  SET_VECTOR_ELT(dimnames, 1, nam);
  setAttrib(ans, R_DimNamesSymbol, dimnames);
  UNPROTECT(2);
  return(ans);
}
Run Code Online (Sandbox Code Playgroud)

如果将该代码放在名为 的文件中myMat.c,则可以通过以下行对其进行测试。我正在使用 Ubuntu,因此如果您使用的是 Windows myMat.somyMat.dll则必须更改为。

R CMD SHLIB myMat.c
Rscript -e 'dyn.load("myMat.so"); .Call("myMat", c("A","C","G","T"))'
Run Code Online (Sandbox Code Playgroud)