r - How to find the min of the previous n values for every element of a vector? -
so far use loops within function this:
# x vector of numbers # [1] 0 1 -1 -5 100 20 15 function(x,n){ results <- numeric(length(x)-n+1) for(i in 1:(length(x)+1-n)){ results[i] <- min(x[i:(i+n-1)]) } return(results) } ## outputs x , n = 3 # [1] -1 -5 -5 -5 15
i wondering if there more efficient solution potentially not require looping.
edit::
i ran 2 of solutions microbenchmark on vector 6019 observations. when time (/figure out how), can try each solution various observation sizes see effectiveness of each solution. now:
rcpp solution:
> microbenchmark(nmin(x,3)) unit: microseconds expr min lq mean median uq max neval nmin(x, 3) 53.885 54.313 57.01953 54.7405 56.023 93.656 100
catools solution:
microbenchmark(runmin(x[[1]],3,endrule='trim')) unit: microseconds expr min lq mean median uq max neval runmin(x[[1]], 3, endrule = "trim") 231.788 241.8385 262.6348 249.964 262.5795 833.923 100
zoo solution:
> microbenchmark(rollapply(x[[1]],3,min)) unit: milliseconds expr min lq mean median uq max neval rollapply(x[[1]], 3, min) 42.2123 47.2926 50.40772 50.33941 52.50033 98.46828 100
my solution:
> microbenchmark(ndaylow(x[[1]],3)) unit: milliseconds expr min lq mean median uq max neval ndaylow(x[[1]], 3) 13.64597 14.51581 15.67343 15.33006 15.71324 63.68687 100
sounds use-case rcpp. copy-paste , use other function. sure there many ways make more efficient (what mean not particularly @ c++ , i'm pretty sure can make use of nice stls here):
require(rcpp) rcpp::cppfunction( 'integervector nmin( numericvector x , int n ){ int n = x.size(); integervector out(n-n+1); for( int = 0; < out.size(); ++i){ int nmin=x[i]; for( int j = 0; j < n; ++j){ int tmp=x[j+i]; if( tmp < nmin ){ nmin=tmp; } } out[i]=nmin; } return out; }') nmin(x,3) #[1] -1 -5 -5 -5 15 nmin(x,7) #[1] -5
it's 30-fold quicker runmin
:
print( microbenchmark(runmin(x,3,endrule='trim'),nmin(x,3),unit="relative") , digits = 1 ) #unit: relative # expr min lq median uq max neval # runmin(x, 3, endrule = "trim") 55 41 36 34 19 100 # nmin(x, 3) 1 1 1 1 1 100
Comments
Post a Comment