In line 5, we need to determine whether all of thekvalues starting
atx[i]—that is, all of the values inx[i],x[i+1],...,x[i+k-1]—are 1s. The
expressionx[i:(i+k-1)]gives us this range inx, and then applyingall()
tells us whether there is a run there.
Let’s test it.
> y <- c(1,0,0,1,1,1,0,1,1)
> findruns(y,3)
[1] 4
> findruns(y,2)
[1]458
> findruns(y,6)
NULL
Although the use ofall()is good in the preceding code, the buildup
of the vectorrunsis not so good. Vector allocation is time consuming. Each
execution of the following slows down our code, as it allocates a new vector
in the callc(runs,i). (The fact that new vector is assigned torunsis irrele-
vant; we still have done a vector memory space allocation.)
runs <- c(runs,i)
In a short loop, this probably will be no problem, but when application
performance is an issue, there are better ways.
One alternative is to preallocate the memory space, like this:
1 findruns1 <- function(x,k) {
2 n <- length(x)
3 runs <- vector(length=n)
4 count <- 0
5 for (i in 1:(n-k+1)) {
6 if (all(x[i:(i+k-1)]==1)) {
7 count <- count + 1
8 runs[count] <- i
9 }
10 }
11 if (count > 0) {
12 runs <- runs[1:count]
13 } else runs <- NULL
14 return(runs)
15 }
In line 3, we set up space of a vector of lengthn. This means we avoid
new allocations during execution of the loop. We merely fillruns, in line 8.
Just before exiting the function, we redefinerunsin line 12 to remove the
unused portion of the vector.
36 Chapter 2