Если вы открыты для 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 и никакого управления памятью.