How to trim an R vector?

r, vectorization

Solution

All of the previous solutions implicitly check every element of the vector. As @Robert Kubrick points out, this does not take advantage of the fact that the vector is already sorted.

To take advantage of the sorted nature of the vector, you can use binary search (through `findInterval`) to find the start and end indexes without looking at every element:

n<-1e9
v<--3:(n+3)
system.time(a <- v [v>=1 & v <=n]) # 68 s
system.time(b <- v[do.call(seq,as.list(findInterval(c(1,n),v)))]) # 15s
identical(a,b) # TRUE

It is a little clumsy, and there is some discussion that the binary search in `findInterval` may not be entirely efficient, but the general idea is there.

As was pointed out in the comments, the above only works when the index is in the vector. Here is a function that I think will work:

in.range <- function(x, lo = -Inf, hi = +Inf) {
   lo.idx <- findInterval(lo, x, all.inside = TRUE)
   hi.idx <- findInterval(hi, x)
   lo.idx <- lo.idx + x[lo.idx] >= lo
   x[seq(lo.idx, hi.idx)]
}

system.time(b <- in.range(v, 1, n) # 15s

Problem

I have the following sorted vector: ``` > v [1] -1 0 1 2 4 5 2 3 4 5 7 8 5 6 7 8 10 11 ``` How can I remove the -1, 0, and 11 entries without looping over the whole vector, either with a user loop or implicitly with a language keyword? That is, I want to trim the vector at each edge and only at each edge, such that the sorted sequence is within my min,max parameters 1 and 10. The solution should assume that the vector is sorted to avoid checking every element. This kind of solutions can come handy in vectorized operations for very large vectors, when we want to use the items in the vector as indexes in another object. For one application see this thread.

Original source

Related problems