Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

exists and sapply: why are these functions different?

Tags:

scope

r

sapply

Why are the two functions fn and gn below different? I don't think they should be, but I must be missing something.

vars <- letters[1:10]
a <- b <- 1
fn <- function (d) {
    sapply( vars, exists )
}
gn <- function (d) {
    sapply( vars, function (x) { exists(x) } )
}
fn(d=2)
#    a     b     c     d     e     f     g     h     i     j 
# TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE 
gn(d=2)
#    a     b     c     d     e     f     g     h     i     j 
# TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE 
exists("i")
# [1] FALSE

There are two differences:

  1. gn(d=2) says that d exists, but why doesn't fn(d=2)?
  2. fn(d=2) says that i exists, when gn(d=2) does not. This is puzzling, because I haven't defined i anywhere.

Note: This is on R version 3.2.0, it seems the second behavior is new to that version (see below).

like image 955
petrelharp Avatar asked Jun 17 '15 00:06

petrelharp


People also ask

What does sapply do in R?

The sapply() function helps us in applying functions on a list, vector, or data frame and returns an array or matrix object of the same length. The sapply() function in the R Language takes a list, vector, or data frame as input and gives output in the form of an array or matrix object.

Which command applies the function to each element in the given vector and returns a list that contains all the results?

16.3 sapply() Essentially, sapply() calls lapply() on its input and then applies the following algorithm: If the result is a list where every element is length 1, then a vector is returned. If the result is a list where every element is a vector of the same length (> 1), a matrix is returned.

What should be the command if we want to get help about apply function?

You can use the help section to get a description of this function. the apply function looks like this: apply(X, MARGIN, FUN).


1 Answers

Why i is different...

It looks like there were changes in R 3.2. An index variable i has been added to the current environment of lapply (which is what sapply actually calls). This goes along with the new behavior to force evaluation of the parameters passed along to the function you are applying over. This means that you now have access to the index of the current iteration you are on in the loop.

The reason fn and gn behave differently is that exists() looks in the environment where it is called. In the case of fn, that is the environment where this i variable has been created. In the case of gn, it's looking in the environment of your anonymous function. When R cannot find a symbol in the local environment, it searches environments based on where functions where defined, not where they are called. This means R will not find the i variable since your anonymous function is defined in a place where the i variables does not exist.

We can write a little helper function to make it easier to grab the current index.

idx <- function() get("i", parent.frame(2))
sapply(letters[1:3], function(x) paste(idx(), x))
#     a     b     c 
# "1 a" "2 b" "3 c"

As far as I can tell this is currently undocumented behavior. It may change in future versions of R.

Why d is different...

The discrepancy with the d variable is a more direct scoping issue. Again R is creating a new environment which it is using to call the function exists. The parent of this environment is the base environment. So when you call exists it looks where it was called from (which is this environment where i exists) and since it doesn't find d there, it searches the next parent which is the base environment. The current function environment is never searched. You could explicitly search the current environment with

fn <- function (d) {
    sapply( vars, exists, where=environment() )
}
fn(d=2)
#    a     b     c     d     e     f     g     h     i     j 
# TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE 

For more information on environments in R I suggest you read the Environments section of Advanced R

like image 175
MrFlick Avatar answered Oct 10 '22 23:10

MrFlick