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