2011-04-18 8 views
6

Estoy escribiendo un paquete R que manipula Matrices en C. Actualmente, las matrices devueltas a R tienen números para los nombres de fila/columna. Preferiría asignar mis propios nombres de fila/columna cuando modifique el objeto en C.R extensión en C, configuración de nombres de fila/columna de matriz

He buscado en Google alrededor de una hora, pero todavía no he encontrado una buena solución. Lo más cerca que he encontrado son los dimnames, pero quiero nombrar cada columna, no solo las dos dimensiones. Las matrices son más grandes que 4x4, a continuación solo hay un pequeño ejemplo de lo que quiero hacer.

El número de filas es 4^x donde X es la longitud del nombre de fila

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 nombra cada fila y columna, que un vistazo superficial a? Dimnames mostrará dimnames (mat) <- list (c ("A", "C", "G", "T"), c (" A "," C "," G "," T ")) también hay? Rownames y? Colnames – mdsumner

Respuesta

3

Como dijo Jim, esto es mucho más fácil de hacer en R. Estoy pasando los nombres en la función C a través de la nam argumento.

#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); 
} 

Si pones ese código en un archivo llamado myMat.c, puede probarlo a través de la línea de abajo. Estoy usando Ubuntu, por lo que tendrá que cambiar myMat.so a myMat.dll si está en Windows.

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

Hmm, bueno, el problema es meter las cuerdas en los objetos de SEXP. PROTECT (colnames = allocVector (VECSXP, 4)); \t PROTEGER (A = NEW_CHARACTER (1)); SET_STRING_ELT (A, 0, mkChar ("A")); SET_VECTOR_ELT (nombres de fila, 0, A); SET_VECTOR_ELT (nombres de fila, 1, A); SET_VECTOR_ELT (nombres de fila, 2, A); SET_VECTOR_ELT (nombres de fila, 3, A); – Nick

+0

¿Querías decir 'change "myMat.so" to "myMat.dll"? Por el momento, la forma en que lo lee parece que te estás refiriendo a 'myMat.c' como lo que se debe cambiar a' myMat.dll'. –

+0

@Gavin: estás en lo cierto; editado –

1

La nota anterior es instructivo. Los dimnames son una lista con el mismo número de elementos que las dimensiones del conjunto de datos, donde cada elemento corresponde a los elementos numéricos a lo largo de esa dimensión, es decir, list(c('a','c','g','t'), c('a','c','g','t')).

Para establecer que en C, que recomendaría:

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

Tendrás a continuación, establecer los elementos rowname y nombrecol pertinentes. En general, este material es mucho más fácil de hacer en R.

Jim

+0

Debe establecer los elementos de' dimnames' antes de llamar a 'setAttrib'. @Nick: también recomendaría hacer esto en R. –

+0

Jim, también tendría que estar DESPROTEGIDO (4). Lo probé y no pareció funcionar. Aunque seguiré intentándolo – Nick

+0

También necesitarías al menos lo siguiente, pero todavía no está funcionando ...SET_STRING_ELT (rownames, 0, mkChar ("A")); SET_VECTOR_ELT (dimnames, 0, rownames); SET_VECTOR_ELT (dimnames, 1, colnames); – Nick

6

Si usted está abierto a C++ en lugar de C, entonces Rcpp puede hacer esto un poco más fácil. Acabamos de crear un objeto de lista con filas y nombres de columna como lo haríamos en R, y asignamos a que el atributo dimnames del objeto de matriz:

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> 

La asignación real de los nombres de columna y fila es tan Manual .. porque el estándar actual de C++ no permite la asignación directa de vectores en la inicialización, pero eso cambiará.

Editar: me he dado cuenta de que puedo, por supuesto, utilizar el método estático create() en la fila y COLNAMES también, lo que hace que sea un poco más fácil y más corto todavía

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> 

Por lo tanto, se han reducido a tres o cuatro declaraciones, sin monkeys con PROTECT/UNPROTECT y sin administración de memoria.

+0

Gracias por la sugerencia, pero desafortunadamente estoy limitado a C. – Nick

+0

No porque realmente todas las instalaciones R que tienen C por gcc también tengan C++ a través de g ++, y el código del objeto interopera. –

+0

¿Hay '.attr (" nombres de fila ")', '.attr (" colnames ")', '.attr (" nombres ")' también, en caso de que uno solo quiera especificar nombres de columna o fila? ¿Dónde encontraría esta información en los documentos? – highBandWidth

Cuestiones relacionadas