2011-04-18 65 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