0% found this document useful (0 votes)
22 views4 pages

Advanced R Programming Concepts

The document discusses the components of functions in R - the body, formals, and environment. It describes primitive functions which contain no R code and have NULL formals, body and environment. Lexical scoping is explained, where R looks up symbol values based on how functions were defined rather than called. Dynamic scoping is also covered. Applying functions using do.call() and environments are discussed. Matrix and data frame manipulation functions like apply(), sweep(), outer(), tapply() and split() are explained.

Uploaded by

Natasa
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views4 pages

Advanced R Programming Concepts

The document discusses the components of functions in R - the body, formals, and environment. It describes primitive functions which contain no R code and have NULL formals, body and environment. Lexical scoping is explained, where R looks up symbol values based on how functions were defined rather than called. Dynamic scoping is also covered. Applying functions using do.call() and environments are discussed. Matrix and data frame manipulation functions like apply(), sweep(), outer(), tapply() and split() are explained.

Uploaded by

Natasa
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Advanced R (H.

Wickham)
Functions
What are the components of a function?
• body(): the code inside the function
• formals(): the list of arguments which controls how you can call the function.
• environment(): the "map" of the location of the function’s variables.
f <- function(x) x^2

formals(f)

## $x
body(f)

## x^2
environment(f)

## <environment: R_GlobalEnv>
Only primitive functions contain no R code: their formals, body and environment are NULL.
sum

## function (..., [Link] = FALSE) .Primitive("sum")


formals(sum)

## NULL
Primitive functions are only found in the base() package; since they operate at a lower level, they can be
more efficient (primitive replacement copies don’t have to make copies), yet they behave differently from
other functions.

Scoping
Scoping is the set of rules governing how R looks up the value of a symbol.
• *Lexical scoping*: implemented automatically at the language level; it looks up symbol values based
on how functions were created, now how they are nested when they are called. With this, you don’t
need to know how the function is called to figure out where the value of a variable will be looked up. It
determines where to look for values, not when to look for them. R looks for values when the function is
*run*, not when it is created. The output of a function can therefore be different depending on objects
outside its environment.
• *Dynamic scoping*: used in select functions to save typing during interactive analysis;

Lexical scoping
If a name is not defined inside a function, R will look one level up, and the same applies if a function is
defined inside another function.
If a function is defined inside another function: look inside the current function, then where that function
was defined, and so on, all the way up to the global environment, and then on to the other loaded packages.

1
Dynamic scoping

f <- function() x

x <- 15

f()

## [1] 15
codetools::findGlobals(f) # Find the global environment using findGlobals()

## [1] "x"
# Another way is to change the environment of a function to one that contains nothing

# could not find it - hence you emptied the environment

You want to avoid the behaviour above, because the function is no longer self-contained. Detect the error
by using findGlobals().You can manually change the environment to an empty oneenvironment (f) <-
emptyenv(), but this does not work, because R relies on lexical scoping to find everything. You can never
make a function entirely self-contained, because you must rely on functions in the base package.
# Case 1: Define the names inside the function

f <- function(){

x<-1
y<-2
c(x,y)

f() # Print it

## [1] 1 2
rm(f) # remove it

# Case 2: no not define the name inside the function

x <- 2
g <- function(){
y <- 1
c(x,y)

# R will look one level up

g()

## [1] 2 1

2
rm(x,g)

# Case 3: the function is defined inside another function


# Look inside the function, then where the function was defined, and so on, all the way to the global en

x=1
h=function(){
y=2
i=function(){
z=3
c(x,y,z)
}
i()
}

h()

## [1] 1 2 3
rm(x,h)

j=function(x)
{
y=2
function(){
c(x,y)
}
}

k=j(1)

k()

## [1] 1 2
Use [Link]() to send the following list to mean
args <- list(1:10, [Link]=TRUE)

[Link](mean, list(1:10, [Link]=TRUE)) # Use [Link]()

## [1] 5.5
mean(1:10, [Link] = TRUE) #This is equivalent to the above

## [1] 5.5
Note that function arguments in R are evaluated lazily: they are only evaluated if they are actually used. If
you want to ensure that an argument is evaluated, use force().
S3: generic-function OO – different from Java, C++ and C#.
S4 is more formal.

3
Environment
The environment is the data structure that powers scoping. Environments can be useful data structures in
their own right, because they have reference semantics.
The main function of an environment is to associated (bind) a set of names to a set of values – it is essentially
a bag of names.
globalenv() is the interactive workspace. The parent of the environment is the last package that you
attached with library() or require(). The environment() is the current environment. Use search() to
access the environment.
Condition handling is used to take actions based on what you get. Defensive programming is used to avoid
common problems before they occur.
Use R functions: traceback() (lists the sequences that lead to error) and browser() (opens an interactive
system at an arbitrary location in the code).
Defensive programming is the art of making code fail in a well-defined manner even when something unexpected
occurs – “fail fast”: as soon as something wrong is discovered, signal an error.
A functional is a function that takes a function as an input an returns a vector as output: e.g., lapply(),
sapply().

Manipulating matrices and data frame


apply(), sweep(), outer() work with matrices;
tapply() summarises a vector by groups defined by another vector.
plyr package generalises tapply(), making it easier to work with data frames, lists or arrays as inputs; data
frames, lists, or arrays as outputs.
apply() is a variant of sapply() that works with matrices and arrays. Think of it as an operation that
summarises a matrix or array by collapsing each row or column to a single number.
sweep() allows you to sweep out the values of a summary statistic; it is often used by apply() to standardise
arrays.
outer() takes multiple vector inputs and creates a matrix or array output where the input function is run
over every combination of inputs.
outer(1:3, 1:10, "*")

## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 1 2 3 4 5 6 7 8 9 10
## [2,] 2 4 6 8 10 12 14 16 18 20
## [3,] 3 6 9 12 15 18 21 24 27 30
outer(1:3, 1:10)

## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 1 2 3 4 5 6 7 8 9 10
## [2,] 2 4 6 8 10 12 14 16 18 20
## [3,] 3 6 9 12 15 18 21 24 27 30
split() takes two inputs and returns a list which groups elements together from the first vector according
to elements, or categories, from the second vector.
tapply() is just a combination of split() and sapply().
A function operator is a function that takes one or more functions as input and returns a function as
output. You can do without them, but they make your code more readable.

You might also like