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

问题描述

| 我正在编写一个R包,用于在C中操纵矩阵。当前,返回到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

解决方法

正如Jim所说的那样,这在R中更容易实现。我正在通过
nam
参数将名称传递给C函数。
#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,nam);
  SET_VECTOR_ELT(dimnames,1,nam);
  setAttrib(ans,R_DimNamesSymbol,dimnames);
  UNPROTECT(2);
  return(ans);
}
如果将该代码放在名为
myMat.c
的文件中,则可以通过下面的行对其进行测试。我正在使用Ubuntu,因此如果您使用Windows,则必须将ѭ4更改为ѭ5。
R CMD SHLIB myMat.c
Rscript -e \'dyn.load(\"myMat.so\"); .Call(\"myMat\",c(\"A\",\"C\",\"G\",\"T\"))\'
,如果您对C ++而不是C持开放态度,那么Rcpp可以使此操作变得容易一些。我们只需要像在R中那样创建一个具有行和列名称的列表对象,并将其分配给矩阵对象的the7ѭ属性:
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> 
列名和行名的实际分配是如此手动... ...因为当前的C ++标准不允许在初始化时直接分配向量,但是这种情况会发生变化。 编辑:我只是意识到我当然也可以在行和别名上使用静态
create()
方法,这使得此操作更简单,更短
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(),plugin=\"Rcpp\")
R> fun()
   ee ff
cc 42 42
dd 42 42
R> 
因此,我们只剩下3或4条语句,不会在PROTECT / UNPROTECT上胡闹,也没有内存管理。,上面的说明具有指导意义。昏暗的名字是一个具有与数据集维度相同数量的元素的列表,其中每个元素对应于沿该维度的数量元素,即“ 11”。 要在C中进行设置,我建议:
PROTECT(dimnames = allocVector(VECSXP,2));
PROTECT(rownames = allocVector(STRSXP,4));
PROTECT(colnames = allocVector(STRSXP,4));
setAttrib( ?,dimnames);
然后,您必须设置相关的行名和列名元素。通常,在R中执行此操作要容易得多。 吉姆