这是我想翻译为c ++来加快处理速度的一种R方法
setMethod("[[", signature=signature(x="ncdfFlowSet"),
definition=function(x, i, j, use.exprs = TRUE, ...)
{
#subset by j
if(!missing(j)){
if(is.character(j)){
j <- match(j, localChNames)
if(any(is.na(j)))
stop("subscript out of bounds")
}
fr@parameters <- fr@parameters[j, , drop = FALSE]
localChNames <- localChNames[j]
}
#other stuff
})
在凯文的不错的工作矢量子集让我的生活更容易些了很多j
子集
// [[Rcpp::export]]
Rcpp::S4 readFrame(Rcpp::S4 x
, std::string sampleName
, Rcpp::RObject j_obj
, bool useExpr
)
{
Rcpp::Environment frEnv = x.slot("frames");
Rcpp::S4 frObj = frEnv.get(sampleName);
Rcpp::S4 fr = Rcpp::clone(frObj);
//get local channel names
Rcpp::StringVector colnames = x.slot("colnames");
Rcpp::StringVector ch_selected;
/*
* subset by j if applicable
*/
int j_type = j_obj.sexp_type();
//creating j index used for subsetting colnames and pdata
Rcpp::IntegerVector j_indx;
if(j_type == STRSXP)//when character vector
{
ch_selected = Rcpp::StringVector(j_obj.get__());
unsigned nCol = ch_selected.size();
j_indx = Rcpp::IntegerVector(nCol);
//match ch_selected to colnames
for(unsigned i = 0 ; i < nCol; i ++)
{
const Rcpp::internal::string_proxy<STRSXP> &thisCh = ch_selected(i);
Rcpp::StringVector::iterator match_id = std::find(colnames.begin(), colnames.end(), thisCh);
if(match_id == colnames.end()){
std::string strCh = Rcpp::as<std::string>(thisCh);
Rcpp::stop("j subscript out of bounds: " + strCh);
}else
{
j_indx(i) = match_id - colnames.begin();
}
}
}
else if(j_type == NILSXP)//j is set to NULL in R when not supplied
{
ch_selected = colnames;
}
else if(j_type == LGLSXP)
{
Rcpp::LogicalVector j_val(j_obj.get__());
ch_selected = colnames[j_val];
#to convert numeric indices to integer
}
else if(j_type == INTSXP)
{
Rcpp::IntegerVector j_val(j_obj.get__());
j_indx = j_val - 1; //convert to 0-based index
ch_selected = colnames[j_indx];
}
else if(j_type == REALSXP)
{
Rcpp::NumericVector j_val(j_obj.get__());
#to convert numeric indices to integer
}
else
Rcpp::stop("unsupported j expression!");
/*
* subset annotationDataFrame (a data frame)
*
*/
if(j_type != NILSXP)
{
Rcpp::S4 pheno = fr.slot("parameters");
Rcpp::DataFrame pData = pheno.slot("data");
Rcpp::CharacterVector pd_name = pData["name"];
Rcpp::CharacterVector pd_desc = pData["desc"];
Rcpp::NumericVector pd_range = pData["range"];
Rcpp::NumericVector pd_minRange = pData["minRange"];
Rcpp::NumericVector pd_maxRange = pData["maxRange"];
Rcpp::DataFrame plist = Rcpp::DataFrame::create(Rcpp::Named("name") = pd_name[j_indx]
,Rcpp::Named("desc") = pd_desc[j_indx]
,Rcpp::Named("range") = pd_range[j_indx]
,Rcpp::Named("minRange") = pd_minRange[j_indx]
,Rcpp::Named("maxRange") = pd_maxRange[j_indx]
);
pheno.slot("data") = plist;
}
然而j
索引在R
通常允许不同类型的输入(character
,logical
或numeric
)。我不知道是否有相同种类的polymorphic
机构(可能通过抽象的矢量指针/参考),以使冗余码(简单地由于不同类型RCPP :: **载体的),用于[-subsetting
在data.frame
以后可以被避免。
我们通常主张将逻辑分为调度步骤和模板化功能步骤。因此,您应该可以使用以下类似的方法解决您的问题:
#include <Rcpp.h>
using namespace Rcpp;
template <typename T>
SEXP readFrame(Rcpp::S4 x, std::string sampleName, T const& j, bool useExpr) {
// use the typed 'j' expression
}
// [[Rcpp::export(subset)]]
SEXP readFrame_dispatch(Rcpp::S4 x, std::string sampleName, SEXP j, bool useExpr)
switch (TYPEOF(j)) {
case INTSXP: return readFrame<IntegerVector>(x, sampleName, j, useExpr);
case REALSXP: return readFrame<NumericVector>(x, sampleName, j, useExpr);
case STRSXP: return readFrame<CharacterVector>(x, sampleName, j, useExpr);
case LGLSXP: return readFrame<LogicalVector>(x, sampleName, j, useExpr);
default: stop("Unsupported SEXP type");
}
return R_NilValue;
}
Rcpp中的设计目标之一是出于速度原因尽可能避免运行时多态-几乎所有多态都是静态完成的,并且理想情况下运行时查找应该只发生一次(除非有时我们被迫回叫R,一些例程)。
调度代码有点丑陋和机械,但是允许这种“样式”的编程。如果将“调度”与“实现”分开,则代码也变得更具可读性,因为您可以将调度的丑陋隐藏在一个位置。
我确实想知道是否存在一些宏魔术可以减少这种形式的分派代码中的代码重复,但是...
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句