Расширение R в C, задающее имена строк / столбцов матрицы

#c #r #matrix

#c #r #матрица

Вопрос:

Я пишу пакет R, который управляет матрицами в C. В настоящее время матрицы, возвращаемые в R, имеют номера для имен строк / столбцов. Я бы предпочел присвоить свои собственные имена строк / столбцов при изменении объекта в C.

Я гуглил около часа, но пока не нашел хорошего решения. Самое близкое, что я нашел, это dimnames, но я хочу назвать каждый столбец, а не только два измерения. Матрицы становятся больше 4×4, ниже приведен лишь небольшой пример того, что я хочу сделать.

Количество строк равно 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
  

Комментарии:

1. dimnames дает ли имя каждой строке и столбцу, на которые бросается беглый взгляд?dimnames покажет dimnames(mat) <- list(c(«A», «C», «G», «T»), c(«A», «C», «G», «T»)) также есть ? имена строк и ?colnames

Ответ №1:

Если вы открыты для C вместо C, то Rcpp может немного упростить это. Мы просто создаем объект list с именами строк и столбцов, как в R, и присваиваем это dimnames атрибуту объекта matrix:

 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> 
  

Итак, у нас осталось три или четыре инструкции, никаких манипуляций с ЗАЩИТОЙ / СНЯТИЕМ защиты и никакого управления памятью.

Комментарии:

1. Спасибо за предложение, но, к сожалению, я ограничен C.

2. На самом деле нет, потому что каждая установка R, имеющая C через gcc, также имеет C через g , и объектный код взаимодействует.

3. Существуют ли также .attr("rownames") , .attr("colnames") .attr("names") также, на случай, если требуется указать только имена столбцов или строк? Где можно найти эту информацию в документах?

4. Да, как вы можете видеть, скажем, в исходниках R или источниках пакетов, устанавливающих эти параметры.

Ответ №2:

Как сказал Джим, это намного проще сделать в 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. Хм, ну, проблема заключается в том, чтобы поместить строки в объекты SEXP. ЗАЩИТИТЬ(colnames = allocVector(VECSXP, 4)); ЗАЩИТИТЬ(A = NEW_CHARACTER(1)); SET_STRING_ELT(A, 0, mkChar(«A»)); SET_VECTOR_ELT (имена строк, 0, A); SET_VECTOR_ELT (имена строк, 1, A); SET_VECTOR_ELT (имена строк, 2, A); SET_VECTOR_ELT (имена строк , 3, А);

2. Ты хотел сказать «изменить»myMat.so «to»myMat.dll «? На данный момент кажется, что то, как это читается, похоже, что вы ссылаетесь на myMat.c как на то, что нужно изменить myMat.dll .

Ответ №3:

Примечание выше поучительно. 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.

джим

Комментарии:

1. Вам нужно задать элементы dimnames перед вызовом setAttrib . @Nick: Я бы также рекомендовал сделать это в R.

2. Джим, это также должно быть НЕЗАЩИЩЕННЫМ (4). Я попробовал это, и, похоже, это не сработало. Я буду продолжать пытаться, хотя

3. Вам также понадобится как минимум следующее, но оно все еще не работает… SET_STRING_ELT(имена строк, 0, mkChar(«A»)); SET_VECTOR_ELT (dimnames, 0, имена строк); SET_VECTOR_ELT (dimnames, 1, colnames);