それは、メモリ内の新しい変数を作成していますか?
入力オブジェクトが実際に数値ベクトル(REALSXP
)であり、単に返すだけの場合、たとえば、 as<NumericVector>(input)
の場合、追加の変数は作成されません。それ以外の場合は、もちろん、返されたオブジェクトに新しいメモリを割り当てる必要があります。例えば、
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector demo(RObject x) {
if (x.sexp_type() == REALSXP) {
return as<NumericVector>(x);
}
return NumericVector::create();
}
/*** R
y <- rnorm(3)
z <- letters[1:3]
data.table::address(y)
# [1] "0x6828398"
data.table::address(demo(y))
# [1] "0x6828398"
data.table::address(z)
# [1] "0x68286f8"
data.table::address(demo(z))
# [1] "0x5c7eea0"
*/
私はそれを行うには良い方法があるかどうかを知りたいです。
まず最初に、 "より良い" を定義する必要があります。
- より速いですか?
- メモリを少なくしますか?
- コードの数が少なくて済みますか?
- もっと慣用ですか?
個人的には、私は最後の定義から始めようとしますが、それはしばしば他のものの1つ以上を伴うからです。例えば、このアプローチでは、我々は
- ではなく、ローカルに
- は、によって決定される文字を排除するためにerase-remove idiomを使用する別の関数オブジェクトを定義し、これを実装しようとしているよりも、標準ライブラリ関数
isdigit
に依存している関数オブジェクトPredicate
を定義しますPredicate
;そして、必要に応じて、(代わりにこの身を実装しようと、再び)double
に残るものに変換するstd::atoi
を使用しています
- はRcppイディオムを使用します -
as
コンバータ - STRSXP
-
std::vector<std::string>
への呼び出しを変換するために
std::transform
結果ベクトルにこれを変換する
#include <Rcpp.h>
using namespace Rcpp;
struct Predicate {
bool operator()(char c) const
{ return !(c == '.' || std::isdigit(c)); }
};
struct Converter {
double operator()(std::string s) const {
s.erase(
std::remove_if(s.begin(), s.end(), Predicate()),
s.end()
);
return s.empty() ? NA_REAL : std::atof(s.c_str());
}
};
// [[Rcpp::export]]
NumericVector convert(RObject obj) {
if (obj.sexp_type() == REALSXP) {
return as<NumericVector>(obj);
}
if (obj.sexp_type() != STRSXP) {
return NumericVector::create();
}
std::vector<std::string> x = as<std::vector<std::string> >(obj);
NumericVector res(x.size(), NA_REAL);
std::transform(x.begin(), x.end(), res.begin(), Converter());
return res;
}
テ最小限の機能のために刺さこの、
x <- c("123 4", "abc 1567.35 def", "abcdef", "")
convert(x)
# [1] 1234.00 1567.35 NA NA
(y <- rnorm(3))
# [1] 1.04201552 -0.08965042 -0.88236960
convert(y)
# [1] 1.04201552 -0.08965042 -0.88236960
convert(list())
# numeric(0)
が、これはベテランCまたはC++プログラマによる手書き何かのようにパフォーマンスのでしょうか?ほとんど間違いない。しかし、ライブラリ関数と一般的なイディオムを使用していたため、バグフリーである可能性があり、簡潔に見ても意図はかなり明白です。にというものが必要な場合は、最適化が必要な場合がありますが、最初にベンチマークやプロファイリングを行う必要はありません。
まず、 'dput(data_set_here)'を使ってデータのサンプルを追加します。第二に、はい。型が 'NumericVector'でなければ、新しいベクトルのメモリを割り当てようとしています。 – coatless