# Introduction

In this example I’ll show some basic examples of for() loops in R using toy examples. Then build some for() loops to address some practical problems, including running a series of regession models. I’ll also show how to debug them by putting them into a function().

# Toy examples

I’ll start off with some toy examples to illustrate basic functionality.

## Toy example 1

• What: For each number 1 through 10, square it and print it out.
• for() starts te loop
• “i” means in index value
• “for i in 1:10” means “for each value of i ranging from 1 to 10”
• print() returns output to the R console.

for(i in 1:10){
print(i^2)
}
## [1] 1
## [1] 4
## [1] 9
## [1] 16
## [1] 25
## [1] 36
## [1] 49
## [1] 64
## [1] 81
## [1] 100

## Toy example 2

Square each value and save it into a vector

First, a vector to hold the data

#replicate the value NA 10 times
storage.vector <- rep(NA,10)

For each value 1 to 10 square it and save it into storage.vector


for(i in 1:10){
storage.vector[i] <- i^2
}

Look at the output

storage.vector
##  [1]   1   4   9  16  25  36  49  64  81 100

## Toy example 3

Draw values from a dataframe, square them, then store them to a dataframe.

First, Make a dataframe to hold the output of the loop

### Setup

A list of values (technicall a vector)

values <- c(1,3,6,12,24,48)

A dataframe holding thse values, and a blank row to hold the output.

output.df <- data.frame(value  = values,
value.squared = NA)

output.df
##   value value.squared
## 1     1            NA
## 2     3            NA
## 3     6            NA
## 4    12            NA
## 5    24            NA
## 6    48            NA

Equivalently we could do this

output.df <- data.frame(value  = c(1,3,6,12,24,48),
value.squared = NA)

The number of values

n.values <- length(values)

Or equivalently, using the dataframe

n.values <- dim(output.df)[1]

### The for() loop

Loop over the i values and square

for (i in 1:n.values){

#get value in row i of the "i" column
i.current <- output.df[i,"value"]

#square it
i.squared <- i.current^2

#save it to dataframe
output.df[i,"value.squared"] <- i.squared
}

output.df
##   value value.squared
## 1     1             1
## 2     3             9
## 3     6            36
## 4    12           144
## 5    24           576
## 6    48          2304

# Debugging a for loop

• A useful way to debug for() loops is to put them into function
• Code must be modified a bit
• Must include return() to actually output from the function the output of the loop
• If you want to save the output need to assign it an object

The for loop

loop.in.function <- function(){
for (i in 1:n.values){

#get value in row i of the "i" column
i.current <- output.df[i,"value"]

#square it
i.squared <- i.current^2

#save it to dataframe
output.df[i,"value.squared"] <- i.squared
}

cat("NOTE: If you want to save the output, must assign it to an object")

#MUST INCLUDE return() to send output out of function land
return(output.df)

}

Run the loop

loop.in.function()
## NOTE: If you want to save the output, must assign it to an object
##   value value.squared
## 1     1             1
## 2     3             9
## 3     6            36
## 4    12           144
## 5    24           576
## 6    48          2304

If you need to debug

debugonce(loop.in.function)

## Toy example 4

For each species in a dataset, how many rows does that species occur in. There are easier ways to anwer this question; this is just for illustration.

### Set up data

Load data for Lloyd et al 2016 PeerJ paper.

dat <- read.csv(file = "PALO_data.csv")

### Look at data

head(dat)
##   Location Species Year Session spp.ann.tot net.hours tot.years.obs
## 1     PALO    BAWW 1997      NA           0        NA             4
## 2     PALO    BAWW 2007      NA           0        NA             4
## 3     PALO    BAWW 2002       1           1     941.0             4
## 4     PALO    BAWW 2010       1           1    1095.0             4
## 5     PALO    BAWW 2008       1           1     591.5             4
## 6     PALO    BAWW 2003      NA           0        NA             4
##   caps.per.1K.nethours net.hours.log
## 1                   NA            NA
## 2                   NA            NA
## 3             1.062699      6.846943
## 4             0.913242      6.998510
## 5             1.690617      6.382662
## 6                   NA            NA

### Prep: vectors holding preliminary info

unique() extracts each unqiue species name

species.vector <- unique(dat$Species) The vector has 23 elements, one for each species. Use length() to determine the number of elements and save it. n.spp <- length(species.vector) A vector index values, 1 through the number of species  index.values <- 1:n.spp Dataframe to hold output output <- data.frame(species.vector, N.rows = NA) ### The Loop We can loop over each species and determine how many rows of that species there are  for(i in index.values){ #extract current species current.spp <- species.vector[i] #determine which rows of the datset have$spp that matches
#the current species
index.current.spp <- which(dat$Species == current.spp) #determine the length of index.current.spp #to count up the number of rows n.current.spp <- length(index.current.spp) #save the output to the row of the dataframe #corresponding to the current #species output$N.rows[i] <- n.current.spp
}



## Toy example 4 revised

I could write this with less preliminary code

#vector of each species
species.vector <- unique(dat$Species) #dataframe to hold output output <- data.frame(species.vector, N.rows = NA) for(i in 1:length(species.vector)){ index.current.spp <- which(dat$Species ==   species.vector[i])

output$N.rows[i] <- length(index.current.spp) } # must return output of the function! return(output) } Run the for loop by calling the function function.for() ## species.vector N.rows ## 1 BAWW 11 ## 2 BCPT 11 ## 3 BITH 11 ## 4 BTBW 11 ## 5 GABU 11 ## 6 GAEL 11 ## 7 GTGT 11 ## 8 HHTA 11 ## 9 HIEM 11 ## 10 HIPE 11 ## 11 HISP 11 ## 12 HITR 11 ## 13 HIWO 11 ## 14 LATH 11 ## 15 NBTO 11 ## 16 OVEN 11 ## 17 RLTH 11 ## 18 RTSO 11 ## 19 SSHA 11 ## 20 WCHT 11 To save the output of the function must assign it to an object output <- function.for() output ## species.vector N.rows ## 1 BAWW 11 ## 2 BCPT 11 ## 3 BITH 11 ## 4 BTBW 11 ## 5 GABU 11 ## 6 GAEL 11 ## 7 GTGT 11 ## 8 HHTA 11 ## 9 HIEM 11 ## 10 HIPE 11 ## 11 HISP 11 ## 12 HITR 11 ## 13 HIWO 11 ## 14 LATH 11 ## 15 NBTO 11 ## 16 OVEN 11 ## 17 RLTH 11 ## 18 RTSO 11 ## 19 SSHA 11 ## 20 WCHT 11 ## Debugging a loop in a function Call debugonce() on the function debugonce(function.for) # A real for() loop The Lloyd data contains time series of counts on 23 species of birds. The following loop runs a regression on each species and saves the output. ## Dataframe to hold coefficients species.vector <- unique(dat$Species)

output.df <- data.frame(Species = species.vector,
intercept = NA,
year = NA)


regression.loop <- function(){
for(i in 1:length(species.vector)){

spp.index <- which(dat\$Species ==
species.vector[i])

data.subset <- dat[spp.index,]

glm.out <- glm(spp.ann.tot ~ Year,
data.subset,
family = "poisson",
offset = net.hours.log)

output.df[i,c("intercept",
"year")] <- coef(glm.out)

}

return(output.df)
}


Run it


output <- regression.loop()

head(output)
##   Species intercept        year
## 1    BAWW -53.89253  0.02355041
## 2    BCPT -72.89729  0.03340652
## 3    BITH  10.34299 -0.00777472
## 4    BTBW -93.09204  0.04367571
## 5    GABU  24.57528 -0.01528563
## 6    GAEL 137.06044 -0.07159340