Rcpp 속도가 가장 중요한 문제인 경우 좋은 방법입니다. 롤링 평균 통계를 사용하여 예제로 설명하겠습니다.
벤치 마크 : Rcpp R
x = sort(runif(25000,0,4*pi))
y = sin(x) + rnorm(length(x),0.5,0.5)
system.time(rollmean_r(x,y,xout=x,width=1.1)) # ~60 seconds
system.time(rollmean_cpp(x,y,xout=x,width=1.1)) # ~0.0007 seconds
코드 Rcpp 및 rollmean_cpp
의 explantion 지금 R 기능
cppFunction('
NumericVector rollmean_cpp(NumericVector x, NumericVector y,
NumericVector xout, double width) {
double total=0;
unsigned int n=x.size(), nout=xout.size(), i, ledge=0, redge=0;
NumericVector out(nout);
for(i=0; i<nout; i++) {
while(x[ redge ] - xout[i] <= width && redge<n)
total += y[redge++];
while(xout[i] - x[ ledge ] > width && ledge<n)
total -= y[ledge++];
if(ledge==redge) { out[i]=NAN; total=0; continue; }
out[i] = total/(redge-ledge);
}
return out;
}')
rollmean_r = function(x,y,xout,width) {
out = numeric(length(xout))
for(i in seq_along(xout)) {
window = x >= (xout[i]-width) & x <= (xout[i]+width)
out[i] = .Internal(mean(y[window]))
}
return(out)
}
대. x
및 y
이 데이터입니다. xout
은 롤링 통계가 요청되는 지점의 벡터입니다. width
은 롤링 창의 너비 * 2입니다. 슬라이딩 윈도우의 끝 부분에 대한 indeces는 ledge
및 redge
에 저장됩니다. 이것들은 기본적으로 x
과 y
의 각 요소에 대한 포인터입니다. 이 indeces는 벡터를 취하고 indents를 입력으로 시작하고 끝내는 다른 C++ 함수 (예 : 중앙값 등)를 호출하는 데 매우 유용 할 수 있습니다. (긴) 디버깅을 위해 rollmean_cpp
의 "자세한"버전을 원하는 사람들을 위해
: 내 질문에 "케빈"에 응답에서
cppFunction('
NumericVector rollmean_cpp(NumericVector x, NumericVector y,
NumericVector xout, double width) {
double total=0, oldtotal=0;
unsigned int n=x.size(), nout=xout.size(), i, ledge=0, redge=0;
NumericVector out(nout);
for(i=0; i<nout; i++) {
Rcout << "Finding window "<< i << " for x=" << xout[i] << "..." << std::endl;
total = 0;
// numbers to push into window
while(x[ redge ] - xout[i] <= width && redge<n) {
Rcout << "Adding (x,y) = (" << x[redge] << "," << y[redge] << ")" ;
Rcout << "; edges=[" << ledge << "," << redge << "]" << std::endl;
total += y[redge++];
}
// numbers to pop off window
while(xout[i] - x[ ledge ] > width && ledge<n) {
Rcout << "Removing (x,y) = (" << x[ledge] << "," << y[ledge] << ")";
Rcout << "; edges=[" << ledge+1 << "," << redge-1 << "]" << std::endl;
total -= y[ledge++];
}
if(ledge==n) Rcout << " OVER ";
if(ledge==redge) {
Rcout<<" NO DATA IN INTERVAL " << std::endl << std::endl;
oldtotal=total=0; out[i]=NAN; continue;}
Rcout << "For interval [" << xout[i]-width << "," <<
xout[i]+width << "], all points in interval [" << x[ledge] <<
", " << x[redge-1] << "]" << std::endl ;
Rcout << std::endl;
out[i] = (oldtotal + total)/(redge-ledge);
oldtotal=total+oldtotal;
}
return out;
}')
x = c(1,2,3,6,90,91)
y = c(9,8,7,5.2,2,1)
xout = c(1,2,2,3,6,6.1,13,90,100)
a = rollmean_cpp(x,y,xout=xout,2)
# Finding window 0 for x=1...
# Adding (x,y) = (1,9); edges=[0,0]
# Adding (x,y) = (2,8); edges=[0,1]
# Adding (x,y) = (3,7); edges=[0,2]
# For interval [-1,3], all points in interval [1, 3]
#
# Finding window 1 for x=2...
# For interval [0,4], all points in interval [1, 3]
#
# Finding window 2 for x=2...
# For interval [0,4], all points in interval [1, 3]
#
# Finding window 3 for x=3...
# For interval [1,5], all points in interval [1, 3]
#
# Finding window 4 for x=6...
# Adding (x,y) = (6,5.2); edges=[0,3]
# Removing (x,y) = (1,9); edges=[1,3]
# Removing (x,y) = (2,8); edges=[2,3]
# Removing (x,y) = (3,7); edges=[3,3]
# For interval [4,8], all points in interval [6, 6]
#
# Finding window 5 for x=6.1...
# For interval [4.1,8.1], all points in interval [6, 6]
#
# Finding window 6 for x=13...
# Removing (x,y) = (6,5.2); edges=[4,3]
# NO DATA IN INTERVAL
#
# Finding window 7 for x=90...
# Adding (x,y) = (90,2); edges=[4,4]
# Adding (x,y) = (91,1); edges=[4,5]
# For interval [88,92], all points in interval [90, 91]
#
# Finding window 8 for x=100...
# Removing (x,y) = (90,2); edges=[5,5]
# Removing (x,y) = (91,1); edges=[6,5]
# OVER NO DATA IN INTERVAL
print(a)
# [1] 8.0 8.0 8.0 8.0 5.2 5.2 NaN 1.5 NaN
비슷한 문제가 있습니다. 다음 질문을 참조하십시오. [Q1] (http://stackoverflow.com/questions/15960352/optimized-rolling-functions-on-irregular-time-series-with-time-based-window?rq=1), [Q2] (http://stackoverflow.com/questions/10465998/sliding-time-intervals-for-time-series-data-in-r/20115018#20115018), [Q3] (http://stackoverflow.com/questions/) 7571788/정규 분석 - 비정규 - 시간 계열? lq = 1). 나는 Rcpp 함수가 작성하기가 쉽고 속도가 빠르다는 것을 알았다. – kdauria