Dr. Alexander Fisher
Duke University
January 18, 2023
if
statements[1] "Other types are coerced to logical if possible."
if the statement is FALSE
, {the code} does not execute
if
is not vectorizedWhile many operators and functions in R
are vectorized,
if
statements are not
any()
and all()
can help us collapse this to a single argument (like “or”/“and” logic)
else if
, else
and ifelse
stop
and stopifnot
We often need to validate user input and function arguments. If our validation fails, we want to report the error and stop execution.
Always place checkpoints upstream (find errors as quickly as possible).
Bad checkpoint placement
Consider two vectors, x and y, each of length one. Write a set of conditionals that satisfy the following.
Test your code with various x and y values. Where did you place the stop execution code?
R supports three types of loops: for
, while
, and repeat
.
for
loops are used to iterate over items in a vector. They have the following basic form:
Automatic printing is turned off in loops.
while
loops interate until a condition is false
repeat
loops repeatedly iterate code until a break
is reached.
next
and break
next
exits the current iteration and advances the looping indexbreak
exits the loopbreak and
next apply only to the innermost of nested loops.You may want to loop over indices of an object as opposed to the object’s values. To do this, consider using one of length()
, seq()
, seq_along()
, and seq_len()
.
Consider the vector x below.
Write R code that prints the perfect squares in x.
Consider z = c(-1, .5, 0, .5, 1)
. Write R code that prints the smallest non-negative integer k satisfying the inequality
\[ |cos(k)−z|<0.001 \]
for each component of z.
A function is comprised of arguments (formals), and code (body).
There are two approaches to returning values from functions in R - explicit and implicit returns.
Explicit - using one or more return function calls
Many functions in R make use of an invisible return value
When defining a function we explicitly define names for the arguments, which become variables within the scope of the function.
When calling a function we can use these names to pass arguments in an alternative order.
R has generous scoping rules, if it can’t find a variable in the current scope (e.g. a function’s body) it will look for it in the next higher scope, and so on.
Additionally, variables defined within a scope only persist for the duration of that scope, and do not overwrite variables at a higher scopes
Arguments to R functions are not evaluated until needed.
Form | Description | Example(s) |
---|---|---|
Prefix | name comes before arguments | log(x, base = exp(1)) |
Infix | name between arguments | +, %>%, %/% |
Replacement | replace values by assignment | names(x) <- c("a", "b") |
Special | all others not defined above | [[, for, break, ( |
To get help on any function, type ?fcn_name in your console, where fcn_name is the function’s name. For infix, replacement, and special functions you will need to surround the function with backticks.
For functions not in the base package, you can generally see their implementation by entering the function name without parentheses (or using the body function).
Write a function when you have copied code more than twice.
Try to use a verb for your function’s name.
Keep argument names short but descriptive.
Add code comments to explain the “why” of your code.
Link a family of functions with a common prefix: pnorm()
, pbinom()
, ppois()
.
Keep data arguments first, then other required arguments, then followed by default arguments. The … argument can be placed last.
To understand computations in R, two slogans are helpful:
Everything that exists is an object.
Everything that happens is a function call.
— John Chambers
John McKinley Chambers is the creator of the S programming language, and core member of the R programming language project. The R programming is often called a successor to the S programming language.