如何在Rcpp中确定存储在SEXP中的对象的class?
How to determine the class of object stored in SEXP in Rcpp?
//[[Rcpp::export]]
int Class_data(SEXP data) {
/*
return 0 if class of data is matrix
else return -1
*/
}
如何确定上述情况下data
的class?如果 data
属于 matrix
class return 0 否则 return -1.
通常,在使用 Rcpp 时,您会事先知道对象的类型,因为您会指定:
//[[Rcpp::export]]
int Class_data(Rcpp::NumericMatrix) {
// code to reduce return to int
return 1;
}
当然,当使用不同的元素类型(例如逻辑、字符和数字)并且具有一个调用函数时,也有例外。我在最后包含了一个这样的例子。
不过,如果你不这样做,最好的办法是在 R 的词汇表中使用 isMatrix
:
INLINE_FUN Rboolean isMatrix(SEXP s)
{
SEXP t;
if (isVector(s)) {
t = getAttrib(s, R_DimSymbol);
/* You are not supposed to be able to assign a non-integer dim,
although this might be possible by misuse of ATTRIB. */
if (TYPEOF(t) == INTSXP && LENGTH(t) == 2)
return TRUE;
}
return FALSE;
}
要处理大量对象(逻辑、字符等),您需要 R 中给出的内部开关 do_is()
function。
虽然这可能有点太大,但您可能需要帮助来分派不同的对象类型。为此,请参阅此示例:
#include <Rcpp.h>
// Create a template generic (look up C++ templates)
template <int RTYPE>
int count_me(Vector<RTYPE> v){
return v.size() ; // Just want to show it can return sizes of different array types
}
// [[Rcpp::export]]
int fake_switch(SEXP x){
// customize with different functions
// Or, just pass different types into the template.
switch( TYPEOF(x) ){
case INTSXP: return count_me<INTSXP>(x); // integers
case REALSXP: return count_me<REALSXP>(x); // numeric
case STRSXP: return count_me<STRSXP>(x); // strings
default: Rcpp::stop("type not handled"); // no support for obj
}
return -1; // should never be trigger but here to make the compiler happy
}
根据您要检查的 object 类型,可能有一个预定义的 Rf_isWhatever
宏,或者您可能需要使用 Rf_inherits(object, "Whatever")
宏,两者都在R 源代码,可通过 Rcpp header 获得。例如,
#include <Rcpp.h>
// [[Rcpp::export]]
int is_matrix(SEXP data) {
return Rf_isMatrix(data) ? 0 : -1;
}
// [[Rcpp::export]]
int is_data_frame(SEXP x) {
return Rf_inherits(x, "data.frame") ? 0 : -1;
}
/*** R
is_matrix(matrix(1:6, 2))
#[1] 0
is_matrix(data.frame(1:5))
#[1] -1
is_data_frame(data.frame(1:5))
#[1] 0
is_data_frame(matrix(1:6, 2))
#[1] -1
*/
作为参考,您可以check the source code查看可用的内容。
//[[Rcpp::export]]
int Class_data(SEXP data) {
/*
return 0 if class of data is matrix
else return -1
*/
}
如何确定上述情况下data
的class?如果 data
属于 matrix
class return 0 否则 return -1.
通常,在使用 Rcpp 时,您会事先知道对象的类型,因为您会指定:
//[[Rcpp::export]]
int Class_data(Rcpp::NumericMatrix) {
// code to reduce return to int
return 1;
}
当然,当使用不同的元素类型(例如逻辑、字符和数字)并且具有一个调用函数时,也有例外。我在最后包含了一个这样的例子。
不过,如果你不这样做,最好的办法是在 R 的词汇表中使用 isMatrix
:
INLINE_FUN Rboolean isMatrix(SEXP s)
{
SEXP t;
if (isVector(s)) {
t = getAttrib(s, R_DimSymbol);
/* You are not supposed to be able to assign a non-integer dim,
although this might be possible by misuse of ATTRIB. */
if (TYPEOF(t) == INTSXP && LENGTH(t) == 2)
return TRUE;
}
return FALSE;
}
要处理大量对象(逻辑、字符等),您需要 R 中给出的内部开关 do_is()
function。
虽然这可能有点太大,但您可能需要帮助来分派不同的对象类型。为此,请参阅此示例:
#include <Rcpp.h>
// Create a template generic (look up C++ templates)
template <int RTYPE>
int count_me(Vector<RTYPE> v){
return v.size() ; // Just want to show it can return sizes of different array types
}
// [[Rcpp::export]]
int fake_switch(SEXP x){
// customize with different functions
// Or, just pass different types into the template.
switch( TYPEOF(x) ){
case INTSXP: return count_me<INTSXP>(x); // integers
case REALSXP: return count_me<REALSXP>(x); // numeric
case STRSXP: return count_me<STRSXP>(x); // strings
default: Rcpp::stop("type not handled"); // no support for obj
}
return -1; // should never be trigger but here to make the compiler happy
}
根据您要检查的 object 类型,可能有一个预定义的 Rf_isWhatever
宏,或者您可能需要使用 Rf_inherits(object, "Whatever")
宏,两者都在R 源代码,可通过 Rcpp header 获得。例如,
#include <Rcpp.h>
// [[Rcpp::export]]
int is_matrix(SEXP data) {
return Rf_isMatrix(data) ? 0 : -1;
}
// [[Rcpp::export]]
int is_data_frame(SEXP x) {
return Rf_inherits(x, "data.frame") ? 0 : -1;
}
/*** R
is_matrix(matrix(1:6, 2))
#[1] 0
is_matrix(data.frame(1:5))
#[1] -1
is_data_frame(data.frame(1:5))
#[1] 0
is_data_frame(matrix(1:6, 2))
#[1] -1
*/
作为参考,您可以check the source code查看可用的内容。