At this point you should be able to write straightforward functions that apply a series of command to several arguments. However, what if you want to do something more complicated?
To do something a set number of times, use a for
loop, like
this: for (
index in
range) { }
The variable used as the index takes on each value listed in the
range, in order. For example, the following for
loop
is used to sum the numbers 1 through 10.
> total <- 0 > for(i in 1:10) + { + total <- total+i + } > total [1] 55This also works for more complicated ranges:
> total <- 0 > for(i in c(1,2,4,5,9)) + total <- total+i > total [1] 21
The following function demonstrates a more useful application of
a for
loop. The function stretch
, described below,
takes a vector and stretches it out, by repeating each element of the
vector the same number of times. (The body of the function creates
a blank vector, and then appends the copies of the original elements).
This is sometimes useful in reformatting data. The guts of this
function uses the function rep
, which generates a vector
containing the first argument repeated the number of times
specified by the second argument.
> stretch <- function(vec, num) + { + output <- c() + for(i in 1:length(vec)) + output <- append(output, rep(vec[i], num)) + } > stretch(c("big bird", "oscar", "snuffleupagus"),4) [1] "big bird" "big bird" "big bird" "big bird" [5] "oscar" "oscar" "oscar" "oscar" [9] "snuffleupagus" "snuffleupagus" "snuffleupagus" "snuffleupagus"Note that
rep
can be used to lengthen the data
in a different way:
> rep(c("big bird", "oscar", "snuffleupagus"),4) [1] "big bird" "oscar" "snuffleupagus" "big bird" [5] "oscar" "snuffleupagus" "big bird" "oscar" [9] "snuffleupagus" "big bird" "oscar" "snuffleupagus"An if statement looks like
if (
expression) { } else { }
The expression can be any logical statement, using <
,>
,
==
, &
(and), |
(or), etc. If the expression
evaluates to true, the part within the first set of brackets will be
executed. If it is false, the else
section, if one exists
(it is optional) will be executed.
> x <- 1 > if(x < 1) {"x is less than one"} else {"x is greater than or equal to one"} [1] "x is greater than or equal to one"A
while
loop can do everything a for
loop can do,
but it can handle more general loops as well. The format is
while (
expression ) { }
The following function will calculate the largest integer power (greater
than zero) of a positive number x
which is less than y
.
The two if
statements ensure that the value of x
will work.
The next two instructions initialize i
and total
. The
while
loop is the guts of this function.
> max.power <- function(x, y) + { + if(x < y & x > 0) + if(x > 1) { + i <- 1 + total <- x + while(total * x < y) { + i <- i + 1 + total <- total * x + } + i + } + else "Infinity" + else NULL + }The two
if
statements ensure that x and y make sense
in this context. The while
statement keeps multiplying
by x
and counting how many times it has done this. In
the end, i
, "Infinity"
or NULL
is returned.
> max.power(2, 100) [1] 6 > max.power(2, 1) NULL > max.power(.5, 100) [1] "Infinity" > max.power(-3, 100) NULL
Question: How would you re-write max.power
to return more
informative messages than ``NULL'' for cases where the first argument
is larger than the second, or the first argument is negative?