Расширение R в C, установка имен строк / столбцов матрицы - PullRequest
6 голосов
/ 19 апреля 2011

Я пишу пакет 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

Ответы [ 3 ]

6 голосов
/ 19 апреля 2011

Если вы открыты для 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() также для строк и имен, что делает это немного проще и короче

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> 

Таким образом, мы дошли до трех или четырех утверждений, никаких манипуляций с PROTECT / UNPROTECT и никакого управления памятью.

3 голосов
/ 19 апреля 2011

Как сказал Джим, это гораздо проще сделать в 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);
}

Если вы поместите этот код в файлназывается myMat.c, вы можете проверить это через строку ниже.Я использую Ubuntu, поэтому вам придется изменить myMat.so на myMat.dll, если вы используете Windows.

R CMD SHLIB myMat.c
Rscript -e 'dyn.load("myMat.so"); .Call("myMat", c("A","C","G","T"))'
1 голос
/ 19 апреля 2011

Примечание выше поучительно. Dimnames - это список с тем же количеством элементов, что и у измерений набора данных, где каждый элемент соответствует числовым элементам в этом измерении, т.е. 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.

джим

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...