The Big R-Book. Philippe J. S. De Brouwer
same, it changes also the value of the variable in the environment above the actual one. The following example makes clear how
<-
only changes the value of x
while the function is active, but <<-
also changes the value of the variable x
in the environment where the function was called from.
# f # Assigns in the current and superior environment 10 to x, # then prints it, then makes it 0 only in the function environment # and prints it again. # arguments: # x -- numeric f <- function(x) {x <<- 10; print(x); x <- ; print(x)} x <- 3 x ## [1] 3 # Run the function f(): f(x) ## [1] 10 ## [1] 0 # Only the value assigned with <<- is available now: x ## [1] 10
Digression – For C++ programmers
If you are moving from C++, you will miss the speed and functionality of passing variable by their pointer. The <<-
operator will provide you the ability to change a variable in the environment above the function.
While it is certainly cool and most probably efficient to change a variable in the environment above the function, it will make your code harder to read and if the function is hidden in a package it might lead to unexpected side effects. This superpower is best used sparingly.
4.4.5 Other Operators
There are of course more operators, that allow to execute common commands more efficiently or apply to certain specific objects such asmatrices. For example, we already have seen the operator :
that creates a sequence. In R it is possible to define your own operators.
# +-+ # This function is a new operator # arguments: # x -- numeric # y -- numeric # returns: # x- y `+-+` <- function(x, y) x - y 5 +-+ 5 ## [1] 0 5 +-+ 1 ## [1] 4 # Remove the new operator: rm(`+-+`)
It is even possible to redefine elementary operators such as +
with the aforementioned code. This is of course not a wise thing to do, but we understand how it can be a fun practical joke or a tricky job interview question.
The following are some common operators that help working with data.
operator – other
# create a list x <- c(10:20) x ## [1] 10 11 12 13 14 15 16 17 18 19 20 # %in% can find an element in a vector 2 %in% x # FALSE since 2 is not an element of x ## [1] FALSE 11 %in% x # TRUE since 11 is in x ## [1] TRUE x[x %in% c(12,13)] # selects elements from x ## [1] 12 13 x[2:4] # selects the elements with index ## [1] 11 12 13 # between 2 and 4
4.5 Flow Control Statements
R is Turing complete and hence offers a range of tools to make choices and repeat certain parts of code. Knowing the different ways to change the flow of a code by if-statements and loops is essential knowledge for each R-programmer.
flow control
4.5.1 Choices
4.5.1.1 The if-Statement
The workhorse to control the flow of actions is the if()
function.
if()
The construct is both simple and efficient.
Function use for if()
if (logical statement) { executed if logical statement is true } else { executed if the logical statement if false }
Note that the else-statement is optional.
This basic construct can also be enriched with else if
statements. For example, we draw a random number from the normal distribution and check if it is bigger than zero.
set.seed(1890) x <- rnorm(1) if (x < 0) { print(‘x is negative’) } else if (x > 0) { print(‘x is positive’) } else { print(‘x is zero’) } ## [1] “x is positive”
It is possible to have more than one else-if statement and/or use nested statements.
x <- 122 if (x < 10) { print(‘less than ten’) } else if (x < 100) { print(‘between 10 and 100’) } else if (x < 1000) { print(‘between 100 and 1000’) } else { print(‘bigger than 1000 (or equal to 1000)’) } ## [1] “between 10 and 1000”
Note that the statements do not necessarily have to be encapsulated by curly brackets if the statement only takes one line.
x <- TRUE y <- pi y <- if (x) 1 else 2 y # y is now 1 ## [1] 1
Note that hybrid forms are possible, but it gets confusing very fast. In the following piece of code the variable y
will not get the value one, but rather six.
z <- y <- if (x) {1; z <- 6} else 2 y # y is now 6 ## [1] 6 z # z is also 6 ## [1] 6
4.5.1.2 The Vectorised If-statement
The function ifelse()
is the vectorised version of the if-function. It allows to use vectors as input and output. While the if-statement is useful for controlling flow in code, the ifelse-function handy for data manipulation.
ifelse()
x <- 1:6 ifelse(x %% 2 == 0, ‘even’, ‘odd’) ## [1] “odd” “even” “odd” “even” “odd” “even”
The ifelse
function can also use vectors as parameters in the output.
x <- 1:6 y <- LETTERS[1:3] ifelse(x %% 2 == 0, ‘even’, y) ## [1] “A” “even” “C” “even” “B” “even” # Note that y gets recycled!
4.5.1.3 The Switch-statement
An if-else construct that assigns one value to a variable based on one other variable can be condensed via