# R para principiantes # PUCE, Quito, 5-8 enero 2010 # Simon Queenborough # MIERCOLES: clase 9 # #################### LOOPS & REPEATS ################## # The classic, Fortran-like loop is available in R. The syntax is a little different, but the idea # is identical; you request that an index, i, takes on a sequence of values, and that one or more # lines of commands are executed as many times as there are different values of i. Here is a # loop executed five times with the values of i from 1 to 5: we print the square of each value: for (i in 1:5) print(i^2) # For multiple lines of code, you use curly brackets {} to enclose material over which the # loop is to work. Note that the ‘hard return’ (the Enter key) at the end of each command line # is an essential part of the structure (you can replace the hard returns by semicolons if you # like, but clarity is improved if you put each command on a separate line): j <- k <- 0 for (i in 1:5) { j <- j + 1 k <- k + i * j print( i + j + k ) } # to calculate the number of individuals of each species: setwd("C:/R_Quito/data") indices <- read.table("indices.txt", header=T) # create empty vector for the results total.sp <- vector() # create a vector of species names spp <- unique(indices$especies) # run a loop through every species name, summing the number of indiviuals of that species for(i in 1:length(spp)) total.sp[i] <- sum(indices$individuos[indices$especies==spp[i]]) total.sp # Here we use a for loop to write a function to calculate factorial x (written x!) which is x! = x × (x-1) × (x-2) × (x-3)... ×2×1 # So 4! = 4 × 3 × 2 = 24. Here is the function: fac1 <- function(x) { f <- 1 if (x < 2) return (1) for (i in 2:x) { f <- f * i f }} # That seems rather complicated for such a simple task, # but we can try it out for the numbers 0 to 5: sapply(0:5,fac1) # There are two other looping functions in R: repeat and while. We demonstrate their use # for the purpose of illustration, but we can do much better in terms of writing a compact # function for finding factorials (see below). First, the while function: fac2 <- function(x) { f <- 1 t <- x while( t > 1 ) { f <- f * t t <- t - 1 } return(f) } # The key point is that if you want to use while, you need to set up an indicator variable (t # in this case) and change its value within each iteration (t<-t-1). We test the function on the # numbers 0 to 5: sapply(0:5,fac2) # Finally, we demonstrate the use of the repeat function: fac3 <- function(x) { f <- 1 t <- x repeat { if ( t < 2 ) break f <- f * t t <- t - 1 } return(f) } # Because the repeat function contains no explicit limit, you need to be careful not to program # an infinite loop. You must have a logical escape clause that leads to a break command: sapply(0:5,fac3) # It is almost always better to use a built-in function that operates on the entire vector and # hence removes the need for loops or repeats of any sort. In this case, we can make use of # the cumulative product function, cumprod. Here it is in action: cumprod(1:5) # This is already pretty close to what we need for our factorial function. It does not work for # 0! of course, because the whole vector would end up full of zeros if the first element in the # vector was zero (try 0:5 and see). The factorial of x>0 is the maximum value from the # vector produced by cumprod: fac4<-function(x) max(cumprod(1:x)) # This definition has the desirable side effect that it also gets 0! correct, because when x is 0 # the function finds the maximum of 1 and 0 which is 1 which is 0!. max(cumprod(1:0)) sapply(0:5,fac4) # Until recently there was no built-in factorial function in R, but now there is: sapply(0:5,factorial) # The next function uses while to generate the Fibonacci series 1, 1, 2, 3, 5, 8,  in which # each term is the sum of its two predecessors. The key point about while loops is that the # logical variable controlling their operation is altered inside the loop. In this example, we # alter n, the number whose Fibonacci number we want, starting at n, reducing the value of # n by 1 each time around the loop, and ending when n gets down to 0. Here is the code: fibonacci<-function(n) { a <- 1 b <- 0 while( n > 0 ) { swap <- a a <- a + b b <- swap n <- n - 1 } b } # An important general point about computing involves the use of the swap variable above. # When we replace a by a+b on line 6 we lose the original value of a. If we had not stored # this value in swap, we could not set the new value of b to the old value of a on line 7. Now # test the function by generating the Fibonacci numbers 1 to 10: sapply(1:10,fibonacci) ## Loop avoidance ## # It is good R programming practice to avoid using loops wherever possible. The use of vector # functions (p. 17) makes this particularly straightforward in many cases. Suppose that you # wanted to replace all of the negative values in an array by zeros. In the old days, you might # have written something like this: for (i in 1:length(y)) { if(y[i] < 0) y[i] <- 0} # Now, however, you would use logical subscripts like this: y[y<0]<- 0