Heather Turner
2005-Jan-24 16:38 UTC
[R] using eval() with pre-built expression inside function
I'm trying to evaluate a pre-built expression using eval(), e.g. dataset <- data.frame(y = runif(30, 50,100), x = gl(5, 6)) # one like this mf <- expression(model.frame(y~x)) eval(mf, dataset, parent.frame()) # rather than this eval(expression(model.frame(y~x)), dataset, parent.frame()) In the example above there is no problem, the problem comes when I try to do a similar thing within a function, e.g. f1 <- function(formula, data) { mt <- terms(formula) mf <- as.expression(as.call(c(as.name("model.frame"), formula = mt))) eval(mf, data, parent.frame()) }> f1(formula = y ~ x, data = dataset)Error in eval(expr, envir, enclos) : Object "y" not found I can get round this by building a call to eval using paste, e.g. f2 <- function(formula, data) { mt <- terms(formula) mf <- as.expression(as.call(c(as.name("model.frame"), formula = mt))) direct <- parse(text = paste("eval(expression(", mf, "), data, parent.frame())")) print(direct) eval(direct) }> f2(formula = y ~ x, data = dataset)expression(eval(expression(model.frame(formula = y ~ x)), data, parent.frame())) y x 1 92.23087 1 2 63.43658 1 3 55.24448 1 4 72.75650 1 5 67.58781 1 ... but this seems rather convoluted. Can anyone explain why f1 doesn't work (when f2 does) and/or suggest a neater way of dealing with this? Thanks Heather Mrs H Turner Research Assistant Dept. of Statistics University of Warwick
Roger D. Peng
2005-Jan-24 16:48 UTC
[R] using eval() with pre-built expression inside function
If you look at the beginning of lm(), you'll see that match.call() is used and name of the function (in this case "f1") is replaced with "model.frame". Does something like this work? f1 <- function(formula, data) { mf <- match.call(expand.dots = FALSE) mf[[1]] <- as.name("model.frame") eval(mf, parent.frame()) } -roger Heather Turner wrote:> I'm trying to evaluate a pre-built expression using eval(), e.g. > > dataset <- data.frame(y = runif(30, 50,100), x = gl(5, 6)) > > # one like this > mf <- expression(model.frame(y~x)) > eval(mf, dataset, parent.frame()) > > # rather than this > eval(expression(model.frame(y~x)), dataset, parent.frame()) > > In the example above there is no problem, the problem comes when I try to do a similar thing within a function, e.g. > > f1 <- function(formula, data) { > mt <- terms(formula) > mf <- as.expression(as.call(c(as.name("model.frame"), formula = mt))) > eval(mf, data, parent.frame()) > } > > >>f1(formula = y ~ x, data = dataset) > > Error in eval(expr, envir, enclos) : Object "y" not found > > I can get round this by building a call to eval using paste, e.g. > > f2 <- function(formula, data) { > mt <- terms(formula) > mf <- as.expression(as.call(c(as.name("model.frame"), formula = mt))) > direct <- parse(text = paste("eval(expression(", mf, > "), data, parent.frame())")) > print(direct) > eval(direct) > } > > >>f2(formula = y ~ x, data = dataset) > > expression(eval(expression(model.frame(formula = y ~ x)), data, > parent.frame())) > y x > 1 92.23087 1 > 2 63.43658 1 > 3 55.24448 1 > 4 72.75650 1 > 5 67.58781 1 > ... > > but this seems rather convoluted. Can anyone explain why f1 doesn't work (when f2 does) and/or suggest a neater way of dealing with this? > > Thanks > > Heather > > Mrs H Turner > Research Assistant > Dept. of Statistics > University of Warwick > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html >-- Roger D. Peng http://www.biostat.jhsph.edu/~rpeng/
Heather Turner
2005-Jan-25 09:23 UTC
[R] using eval() with pre-built expression inside function
Sorry, I forgot to add to my original post that I want to use the "envir" argument of eval() so that I can specify a secondary data source as follows: eval(expression(model.frame(formula, data = lookHereFirst), envir = lookHereSecond, enclos = lookHereThird) Your version of f1 does produce the desired model frame, but does this by passing all the data to model.frame() directly, i.e. it evaluates model.frame(formula = y~x, data = dataset) However, if I adapt your f1 as follows: f1 <- function(formula, data) { mf <- match.call(expand.dots = FALSE) mf[[1]] <- as.name("model.frame") print(mf) mf } it still works if some of the data is provided through the "data" argument of model.frame() and the rest of the data is provided through the "envir" argument of eval():> test1 <- f1(formula = y ~ x, data = dataset[,1, drop = FALSE])model.frame(formula = y ~ x, data = dataset[, 1, drop = FALSE])> eval(test1, dataset[,2,drop = FALSE], parent.frame())y x 1 66.71259 1 2 83.21937 1 3 85.24412 1 4 88.10189 1 5 75.71918 1 .... So you have provided a solution, but I still don't understand why I can't construct the call as I was trying to before: f2 <- function(formula, data) { mf <- as.call(c(as.name("model.frame"), formula = formula, data = substitute(data))) print(mf) mf } This doesn't work:> test2 <- f2(formula = y ~ x, data = dataset[,1, drop = FALSE])model.frame(formula = y ~ x, data = dataset[, 1, drop = FALSE])> eval(test2, dataset[,2,drop = FALSE], parent.frame())Error in eval(expr, envir, enclos) : Object "x" not found Apparently test1 and test2 are not identical, but I can't see why, which may be the root of my problem here. Can anyone explain why they are different? Thanks Heather>>> "Roger D. Peng" <rpeng at jhsph.edu> 01/24/05 04:48pm >>>If you look at the beginning of lm(), you'll see that match.call() is used and name of the function (in this case "f1") is replaced with "model.frame". Does something like this work? f1 <- function(formula, data) { mf <- match.call(expand.dots = FALSE) mf[[1]] <- as.name("model.frame") eval(mf, parent.frame()) } -roger Heather Turner wrote:> I'm trying to evaluate a pre-built expression using eval(), e.g. > > dataset <- data.frame(y = runif(30, 50,100), x = gl(5, 6)) > > # one like this > mf <- expression(model.frame(y~x)) > eval(mf, dataset, parent.frame()) > > # rather than this > eval(expression(model.frame(y~x)), dataset, parent.frame()) > > In the example above there is no problem, the problem comes when I try to do a similar thing within a function, e.g. > > f1 <- function(formula, data) { > mt <- terms(formula) > mf <- as.expression(as.call(c(as.name("model.frame"), formula = mt))) > eval(mf, data, parent.frame()) > } > > >>f1(formula = y ~ x, data = dataset) > > Error in eval(expr, envir, enclos) : Object "y" not found > > I can get round this by building a call to eval using paste, e.g. > > f2 <- function(formula, data) { > mt <- terms(formula) > mf <- as.expression(as.call(c(as.name("model.frame"), formula = mt))) > direct <- parse(text = paste("eval(expression(", mf, > "), data, parent.frame())")) > print(direct) > eval(direct) > } > > >>f2(formula = y ~ x, data = dataset) > > expression(eval(expression(model.frame(formula = y ~ x)), data, > parent.frame())) > y x > 1 92.23087 1 > 2 63.43658 1 > 3 55.24448 1 > 4 72.75650 1 > 5 67.58781 1 > ... > > but this seems rather convoluted. Can anyone explain why f1 doesn't work (when f2 does) and/or suggest a neater way of dealing with this? > > Thanks > > Heather > > Mrs H Turner > Research Assistant > Dept. of Statistics > University of Warwick > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html >-- Roger D. Peng http://www.biostat.jhsph.edu/~rpeng/