Несколько замечаний:
- В матрицах не всегда установлены
colnames()
или rownames()
. - Если оно установлено, то объект имеет атрибут
dimnames
.
- Можно проверить наличие значения через API C для R.
- Альтернативной проверкой существования может быть проверка того, является ли
dimnames
частью атрибутов объекта. - Оттуда проверьте, является ли запись в
dimnames
нулевой.
Давайте проверим это с первой точки, сначала создав матрицу без имен и затем создание одного с именами.Наконец, мы представим более подробную версию вашей функции, которая пытается разрешить матрицу без имен столбцов.
Матричная конструкция
Итак, традиционная матричная конструкция будетbe:
x_no_names = matrix(1:4, nrow = 2)
x_no_names
#> [,1] [,2]
#> [1,] 1 3
#> [2,] 2 4
colnames(x_no_names)
#> NULL
rownames(x_no_names)
#> NULL
attributes(x_no_names)
#> $dim
#> [1] 2 2
Таким образом, * dimnames
для созданной матрицы без имен столбцов или строк не существует.
Что произойдет, если мы присвоим имена столбцов или строкатрибуты?
# Create a matrix with names
x_named = x_no_names
colnames(x_named) = c("Col 1", "Col 2")
rownames(x_named) = c("Row 1", "Row 2")
# View attributes
attributes(x_named)
#> $dim
#> [1] 2 2
#>
#> $dimnames
#> $dimnames[[1]]
#> [1] "Row 1" "Row 2"
#>
#> $dimnames[[2]]
#> [1] "Col 1" "Col 2"
# View matrix object
x_named
#> Col 1 Col 2
#> Row 1 1 3
#> Row 2 2 4
Примечание: объект matrix
теперь имеет атрибут dimnames
.
Реализация проверки в C ++
С нашим пониманием matrix
структура, мы можем проверить:
- Существует ли
dimnames
как атрибут на матрице? - Является ли вторая запись в
dimnames
не NULL
?
Примечание. Этот подход сделает исходную функцию более многословной.Компромисс - это функция, позволяющая избежать необходимости использования SEXP
возвращаемого типа.
#include <Rcpp.h>
// Get column names or empty
// [[Rcpp::export]]
Rcpp::CharacterVector get_colnames(const Rcpp::NumericMatrix &x) {
// Construct a character vector
Rcpp::CharacterVector cn;
// Create a numerical index for each column
Rcpp::IntegerVector a = Rcpp::seq_len(x.ncol());
// Coerce it to a character
Rcpp::CharacterVector b = Rcpp::as<Rcpp::CharacterVector>(a);
// Assign to character vector
cn = b;
if(x.hasAttribute("dimnames")) {
Rcpp::List dimnames = x.attr( "dimnames" ) ;
if(dimnames.size() != 2) {
Rcpp::stop("`dimnames` attribute must have a size of 2 instead of %s.", dimnames.size());
}
// Verify column names exist by checking for NULL
if(!Rf_isNull(dimnames[1]) ) {
// Retrieve colnames and assign to cn.
cn = dimnames[1];
} else {
// Assign to the matrix
colnames(x) = cn;
}
}
return(cn);
}
Проверка варианта C ++
Вызов функции теперь даст:
get_colnames(x_no_names)
#> [1] "1" "2"
get_colnames(x_named)
#> [1] "Col 1" "Col 2"
Первое указывает, что мы используем сгенерированные индексы, тогда как второе указывает на получение значений.