سؤال
كنت أرغب في التحقق مما إذا كان هناك أي خدعة موجودة مسبقا ل na.locf
(من zoo
حزمة), rle
و inverse.rle
في RCpp
?
كتبت حلقة لتنفيذ ، على سبيل المثال.فعلت تنفيذ na.locf(x, na.rm=FALSE, fromLast=FALSE)
على النحو التالي:
#include <Rcpp.h>
using namespace Rcpp;
//[[Rcpp::export]]
NumericVector naLocf(NumericVector x) {
int n=x.size();
for (int i=1;i<n;i++) {
if (R_IsNA(x[i]) & !R_IsNA(x[i-1])) {
x[i]=x[i-1];
}
}
return x;
}
كنت أتساءل فقط أنه نظرا لأن هذه وظائف أساسية تماما، فقد يكون شخص ما قد نفذها بالفعل في RCpp
بطريقة أفضل (قد يكون تجنب حلقة) أو بطريقة أسرع?
المحلول
الشيء الوحيد الذي أود أن أقوله هو أن كنت اختبار ل NA
مرتين لكل قيمة عندما تحتاج فقط إلى القيام بذلك مرة واحدة.اختبار ل NA
ليست عملية حرة.ربما شيء من هذا القبيل:
//[[Rcpp::export]]
NumericVector naLocf(NumericVector x) {
int n = x.size() ;
double v = x[0]
for( int i=1; i<n; i++){
if( NumericVector::is_na(x[i]) ) {
x[i] = v ;
} else {
v = x[i] ;
}
}
return x;
}
هذا لا يزال يفعل أشياء غير ضرورية ، مثل الإعداد v
في كل مرة عندما يمكننا أن نفعل ذلك فقط للمرة الأخيرة ونحن لا نرى NA
.يمكننا تجربة شيء من هذا القبيل:
//[[Rcpp::export]]
NumericVector naLocf3(NumericVector x) {
double *p=x.begin(), *end = x.end() ;
double v = *p ; p++ ;
while( p < end ){
while( p<end && !NumericVector::is_na(*p) ) p++ ;
v = *(p-1) ;
while( p<end && NumericVector::is_na(*p) ) {
*p = v ;
p++ ;
}
}
return x;
}
الآن ، يمكننا تجربة بعض المعايير:
x <- rnorm(1e6)
x[sample(1:1e6, 1000)] <- NA
require(microbenchmark)
microbenchmark( naLocf1(x), naLocf2(x), naLocf3(x) )
# Unit: milliseconds
# expr min lq median uq max neval
# naLocf1(x) 6.296135 6.323142 6.339132 6.354798 6.749864 100
# naLocf2(x) 4.097829 4.123418 4.139589 4.151527 4.266292 100
# naLocf3(x) 3.467858 3.486582 3.507802 3.521673 3.569041 100
لا تنتمي إلى StackOverflow