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.