2011-04-18 114 views
6

我正在编写一个处理C中的矩阵的R包。目前,返回给R的矩阵具有行/列名称的编号。在修改C中的对象时,我宁愿分配自己的行/列名称。R扩展名为C,设置矩阵行/列名称

我已经搜索了大约一个小时,但尚未找到一个好的解决方案。我发现的最接近的名称是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 
+0

dimnames确实为每行和每列指定名称,粗略地看一下?dimnames将显示dimnames(mat)< - list(c(“A”,“C”,“G”,“T”),c(“ A“,”C“,”G“,”T“))还有?rownames和?colnames – mdsumner 2011-04-18 23:54:52

回答

3

吉姆说,这是很容易在河做我传递的名称到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); 
} 

如果你把这些代码在一个名为myMat.c文件,您可以通过以下线路进行测试。我使用的是Ubuntu,因此如果您使用的是Windows,则必须将myMat.so更改为myMat.dll

R CMD SHLIB myMat.c 
Rscript -e 'dyn.load("myMat.so"); .Call("myMat", c("A","C","G","T"))' 
+0

嗯,嗯,问题是让字符串进入SEXP对象。 PROTECT(colnames = allocVector(VECSXP,4)); \t PROTECT(A = NEW_CHARACTER(1)); SET_STRING_ELT(A,0,mkChar(“A”)); SET_VECTOR_ELT(rownames,0,A); SET_VECTOR_ELT(rownames,1,A); SET_VECTOR_ELT(rownames,2,A); SET_VECTOR_ELT(rownames,3,A); – Nick 2011-04-19 00:59:03

+0

您是否想要将“myMat.so”更改为“myMat.dll”?目前,它读取它的方式似乎是指'myMat.c'作为要更改为'myMat.dll'的东西。 – 2011-04-19 07:56:41

+0

@Gavin:你是对的;编辑。 – 2011-04-19 12:41:58

1

上面的音符的长度是有启发性。暗淡名称是与元素数量相同的元素列表,其中每个元素对应于该维度上的数字元素,即list(c('a','c','g','t'), c('a','c','g','t'))

要设置在C,我建议:

PROTECT(dimnames = allocVector(VECSXP, 2)); 
PROTECT(rownames = allocVector(STRSXP, 4)); 
PROTECT(colnames = allocVector(STRSXP, 4)); 
setAttrib(? , R_DimNamesSymbol, dimnames); 

你必须然后设置相关rowname和colname的元素。在一般情况下,这玩意是更容易R.

吉姆做

+0

您需要在调用'setAttrib'之前设置'dimnames'的元素。 @Nick:我也建议在R. – 2011-04-19 00:21:51

+0

Jim中这样做,它也需要被UNPROTECTED(4)。我试了一下,似乎没有工作。我会继续努力,虽然 – Nick 2011-04-19 00:26:06

+0

你还需要至少以下,但它仍然不工作...SET_STRING_ELT(rownames,0,mkChar(“A”)); SET_VECTOR_ELT(dimnames,0,rownames); SET_VECTOR_ELT(dimnames,1,colnames); – Nick 2011-04-19 00:48:31

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> 

行和列名的实际分配是这样的手动.. 。因为当前的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> 

所以我们减少到3或四条语句,不用PROTECT/UNPROTECT和没有内存管理。

+0

感谢您的建议,但不幸的是我仅限于C. – Nick 2011-04-19 23:01:22

+0

不是因为每个通过gcc具有C的R安装程序也都通过g ++具有C++,并且目标代码可以互操作。 – 2011-04-19 23:08:46

+0

如果只想指定列名或行名,那么是否存在'.attr(“rownames”)','.attr(“colnames”)','.attr(“names”)'?在文档中哪里可以找到这些信息? – highBandWidth 2011-12-27 17:53:19

相关问题