[R] Scoping issue? [SUMMARY]

Thaden, John J ThadenJohnJ at uams.edu
Mon Mar 5 22:33:18 CET 2007


A BIG thanks to Luke Tierney and Jim Holtman (and perhaps others? I haven't
seen the latest digest) for pointing out two fixes to some code that was
troubling me. I since found a third problem, and with that, have good code.
Their comments are summarized below this fixed version of the code.

############
mmatplot <- function(colnum, x, y, addto = 0, titleroot = "Column #", ...){
  switch(class(y),
    array = y <- y[, colnum, ],
    list = y <- sapply(X = y, FUN = function(d) d[, colnum]))  #Thanks Luke!
  stopifnot(is.matrix(y))
  matplot(x, y, main = paste(titleroot, colnum), ...)
}
############

This function is a matplot wrapper, useful (I thought) within lapply
or sapply to visually compare several like columns of several matrices. 
Arg y is either a list of matrices with equal number of rows, or 
an array. The first arg, scalar n, gives the column of each matrix
(or array slab) to plot. The fact that it is in first position allows
the program to be used in lapply. par values and matplot args are accepted.

Here is the tester function. It also needed fixing. I had called 
mapply instead of lapply by mistake, but using lapply arguments!

###############
mmatplotTest <- function(){
  A <- array(data = rnorm(90), dim = c(10, 3, 3))
  L <- list(A[, , 1], A[, , 2], A[, , 3])
  oldmf <- par("mfrow")
  par(mfrow = c(2,3))
  # Test with class(y) == "array"
  lapply(X = 1:ncol(A), FUN = mmatplot, x = 1:nrow(A), y = A,
                 titleroot = "Array, column #")
  # Test with class(y) == "list"
  lapply(1:ncol(L[[1]]), mmatplot, x = 1:nrow(L[[1]]), y = L,
                 titleroot = "Listed matrices, column #")
  par(mfrow = oldmf)
}
mmatplotTest()
################

Regarding the original, broken version...

Jim was first to point out that 'colnum' did not exist when my 'paste'
call was made.  I asked why, since I thought lazy evaluation should get
around this problem.  Luke explained...

> In your test function there is no lexically visible definition
> for the `colnum` variable used in defining main, so that error
> is what you expect from lexical scoping.  Lazy evaluation 
> dictates when (and if) the `main` argument is evaluated, but
> the environment in which it is evaluated is determined by the 
> context where the expression is written in the code, i.e. within
> the function mmatplotTest.

Luke also pointed out the source of another error:

> The error you get when you take out the `main` is coming from
> `subset` and is due to the fact that subset is one of those
> functions that uses non-standard evaluation for some of its 
> arguments, in this case `select`.  This makes it (slightly) 
> easier to use at interactive top level but much more complicated
> to use within a function....You need to use another function
> in your sapply call....

I incorporated his suggested alternative above.

Jim suggest sidestepping the entire problem by using explicit, R-level
looping instead of lapply (mapply in my original flawed version!), asserting
that in this case it is even faster, but that, in any case, most time is
spent by the mmatplot function itself, rendering inconsequential the method
of iterating it (also, I should add, rendering rather superfluous my
mmatplot function altogether!).

Thanks again, Luke and Jim, and whoever else considered my problem!

-John Thaden
Little Rock, AR, USA

Confidentiality Notice: This e-mail message, including any a...{{dropped}}



More information about the R-help mailing list