for (...) { ... } while (...) { ... }
my_fun <- function() { ... }
if (...) { ... } else { ... }
for (...)
loopsRuns a block of code for a fixed number of times:
for (item in vector) { # Do something, probably to item }
Remember code blocks are the code within a set of curly brackets – { ... }
– or a single line of code if there are no brackets.
for (...)
loopsRuns a block of code for a fixed number of times:
whole.numbers <- seq(from = 3, to = 6) for (num in whole.numbers) { print(num^2) }
[1] 9 [1] 16 [1] 25 [1] 36
Here, we print out four numbers – the squares of the numbers in the whole.numbers
vector – because that’s how long the vector is.
for (...)
loopsRuns a block of code for a fixed number of times:
halves <- seq(from = 1, to = 2, by = 0.5); total <- 0 for (half in halves) { total <- total + half cat("Adding", half, "gives us", total, "\n") }
Adding 1 gives us 1 Adding 1.5 gives us 2.5 Adding 2 gives us 4.5
total
[1] 4.5
This updates total
with the running total and prints it out.
while (...)
loopsThis runs a block of code while a condition is true:
while (condition.is.TRUE) { # Do something that will (or may) update condition }
while (...)
loopsThis runs a block of code while a condition is true:
half <- 1; increment <- 0.5; total <- 0 while (half <= 2) { total <- total + half cat("Adding", half, "gives us", total, "\n") half <- half + increment }
Adding 1 gives us 1 Adding 1.5 gives us 2.5 Adding 2 gives us 4.5
total
[1] 4.5
We can produce the same result as a for
loop with a bit of work.
while (...)
loopsThis runs a block of code while a condition is true:
half <- 1; increment <- 0.5; total <- 0 while (total < 10) { total <- total + half cat("Adding", half, "gives us", total, "\n") half <- half + increment }
Adding 1 gives us 1 Adding 1.5 gives us 2.5 Adding 2 gives us 4.5 Adding 2.5 gives us 7 Adding 3 gives us 10
half
[1] 3.5
But we can have more complex stopping conditions – has the total got to 10, for instance… but why is half
3.5?
while (...)
loopsThis runs a block of code while a condition is true:
half <- 0.5; increment <- 0.5; total <- 0 while (total < 10) { half <- half + increment total <- total + half cat("Adding", half, "gives us", total, "\n") }
Adding 1 gives us 1 Adding 1.5 gives us 2.5 Adding 2 gives us 4.5 Adding 2.5 gives us 7 Adding 3 gives us 10
half
[1] 3
But we do have to be careful how we write the code block in the loop.
Functions carry out a single fixed task (or function!) for you using the arguments provided:
# Define the function: function_name <- function(first, second) { # Do something to first and second to produce result ... # Return result result } # Then in your script, call the function: function_name(first = 1, second = 2)
Here the function is called function_name()
, and the arguments are first
and second
.
Functions carry out a single fixed task for you using the arguments provided:
add_up <- function(first, second) { first + second } add_up(3, 5)
[1] 8
add_up(first = 3, second = 5)
[1] 8
Here this simple function just adds together its two arguments.
Functions carry out a single fixed task for you using the arguments provided:
subtract <- function(value, from) { from - value } subtract(3, 5)
[1] 2
subtract(from = 3, value = 5)
[1] -2
Note that if you name the arguments, then the order doesn’t matter!
Functions carry out a single fixed task for you using the arguments provided:
add_up <- function(first, second) { result <- first + second } add_up(3, 5)
The last line of code run is what is returned by the function…
Functions carry out a single fixed task for you using the arguments provided:
add_up <- function(first, second) { result <- first + second result } add_up(3, 5)
[1] 8
The last line of code run is what is returned by the function…
Functions carry out a single fixed task for you using the arguments provided:
add_up <- function(first, second) { result <- first + second result cat("The answer is", result, "\n") } result <- add_up(3, 5)
The answer is 8
result
NULL
So you need to be careful what is on that last line!
Functions carry out a single fixed task for you using the arguments provided:
add_up <- function(first, second) { result <- first + second return(result) } add_up(3, 5)
[1] 8
You can explicitly tell the function to end and return a value.
Functions carry out a single fixed task for you using the arguments provided:
add_up <- function(first, second) { result <- first + second return(result) cat("The answer is", result, "\n") } result <- add_up(3, 5) result
[1] 8
If you include a return()
statement the function will end there.
We recommend calculating partial results inside functions whenever it is sensible to make your code easier to read. Imagine we want to calculate: \[(first + second) \times (first + second)\]
add_and_square <- function(first, second) { # Calculate the result added <- first + second squared <- added * added # And return it squared } add_and_square(3, 5)
[1] 64
Doing it all in one go increases the risk of mistakes:
add_and_square <- function(first, second) { (first + second) * first + second } add_and_square(3, 5)
[1] 29
Essential for while
loops and if
statements. They allow us to test whether something is true, and change what lines of code are run depending on the outcome. There are the basic tests:
a == b
: is a
equal to b
? (TRUE
if this is true, FALSE
if this is false)a > b
: is a
greater than b
?a < b
: is a
less than b
?a >= b
: is a
greater than or equal to b
?a <= b
: is a
less than or equal to b
?a != b
: is a
different from b
?Essential for while
loops and if
statements. They allow us to test whether something is true, and change what lines of code are run depending on the outcome. There are the basic tests:
a == b
: is a
equal to b
? (TRUE
if this is true, FALSE
if this is false)a > b
: is a
greater than b
?a < b
: is a
less than b
?a >= b
: is a
greater than or equal to b
?a <= b
: is a
less than or equal to b
?a != b
: is a
different from b
?There are then three basic ways of changing or combining the above:
(a < b) || (c == d)
: is either a
less than b
or c
equal to d
?(a < b) && (c == d)
: is both a
less than b
and c
equal to d
?!((a < b) && (c == d))
: is the above not TRUE
? TRUE
if the above was FALSE
and vice versaRemember to use brackets to ensure you are combining things in the right order. They can be used in the while
loops above to determine whether to continue through the next iteration of the loop, and in the if
statements below to determine what to do next.
if (...) {...}
statementsIf statements allow us to do different things depending on what has gone before in the code.
if (...) {...}
statementsIf statements allow us to do different things depending on what has gone before in the code:
library(codetools) library(RPiR) if (length(findGlobals(add_and_square, merge = FALSE)$variables) != 0) { stop("Function add_and_square() may not use global variable(s): ", findGlobals(add_and_square, merge = FALSE)$variables) }
Here we test if add_and_square()
has any global variables.
if (...) {...}
statementsif (add_and_square(3, 5) == 64) { print("Maths still works") }
if (...) {...} else {...}
if (add_and_square(3, 5) == 64) { print("Maths still works") } else { warning("We have a problem") print(add_and_square(3, 5)) }
Warning: We have a problem
[1] 29
if (...) {...} else {...}
add_and_square <- function(first, second) { # Calculate the result added <- first + second squared <- added * added # And return it squared }
if (...) {...} else {...}
if (add_and_square(3, 5) == 64) { cat("Maths still works\n") } else { cat("We have a problem\n") }
Maths still works
See R section of package website for more details and links to other resources.