Hi there, I wrote a function that wraps MASS::boxcox as: bc <- function(vec) { lam <- boxcox(lm(vec ~ 1)) lam <- lam$x[which.max(lam$y)] (vec^lam - 1)/lam } When I invoke it as:> x <- runif(20) > bc(x)Error in eval(predvars, data, env) : object 'vec' not found I have googled, and rewrote the above function as: bc <- function(vec) { dat <<- data.frame(vec = vec) lam <- boxcox(lm(vec ~ 1, dat)) lam <- lam$x[which.max(lam$y)] rm(dat, envir = .GlobalEnv) (vec^lam - 1)/lam } It works. But, I am wondering why MASS::boxcox have to wrap in such way that have to use the data in .GlobalEnv. Best, Jinsong [[alternative HTML version deleted]]
Hmm, this looks like a buglet/infelicity in update.lm rather than MASS::boxcox per se. Moving to R-devel. I think the story is that update.lm eventually does eval(call, parent.frame()) where the call is extracted from the lm object, but call$formula is unevaluated, and does not contain environment information like formula(obj) would do. Then when the call is evaluated and parent.frame() differs from that of the original call, trouble ensues. A workaround not involving <<- seems to be ... obj <- lm(vec ~ 1) obj$call$formula <- formula(obj) lam <- boxcox(obj) ... I'm not sure whether this is actually fixable. It is the kind of thing where you tend to discover that someone, somewhere has actually been relying on current behaviour... -pd> On 5 Aug 2018, at 14:36 , Jinsong Zhao <jszhao at yeah.net> wrote: > > Hi there, > > I wrote a function that wraps MASS::boxcox as: > > bc <- function(vec) { > lam <- boxcox(lm(vec ~ 1)) > lam <- lam$x[which.max(lam$y)] > (vec^lam - 1)/lam > } > > When I invoke it as: > >> x <- runif(20) >> bc(x) > Error in eval(predvars, data, env) : object 'vec' not found > > I have googled, and rewrote the above function as: > > bc <- function(vec) { > dat <<- data.frame(vec = vec) > lam <- boxcox(lm(vec ~ 1, dat)) > lam <- lam$x[which.max(lam$y)] > rm(dat, envir = .GlobalEnv) > (vec^lam - 1)/lam > } > > It works. But, I am wondering why MASS::boxcox have to wrap in such way that have to use the data in .GlobalEnv. > > Best, > Jinsong > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.-- Peter Dalgaard, Professor, Center for Statistics, Copenhagen Business School Solbjerg Plads 3, 2000 Frederiksberg, Denmark Phone: (+45)38153501 Office: A 4.23 Email: pd.mes at cbs.dk Priv: PDalgd at gmail.com
It is rarely a good idea to invoke lm without providing the inputs in a data frame through the data argument. In this case, just making that change is insufficient though... the boxcox.lm function calls the update function, which re-retreives the data in a new context. The workaround is to supply the data= argument to boxplot which will pass it on to the update function to keep the data visible in the updated lm model. None of this seemed obvious to me from the boxplot help, but I think I would regard using the data= argument to boxplot as being about as essential as it is in lm, because the alternative is to assume that all the data are as-named in the global environment (x is different than vec). ####### library(MASS) bc <- function(vec) { dta <- data.frame( vec = vec ) # Rarely a good idea to call "lm" # without the data argument. model <- lm( vec ~ 1, data = dta ) lam <- boxcox( model, data=dta ) lam <- lam$x[which.max(lam$y)] (vec^lam - 1)/lam } x <- runif(20) bc(x) #' ![](https://i.imgur.com/lhKymfQ.png) #' #> [1] -0.92115159 -0.21776512 -1.20946708 -0.16700312 -0.76096811 #' #> [6] -0.12208801 -0.61723623 -0.78302973 -0.62455538 -1.40636663 #' #> [11] -0.52627869 -0.09377700 -1.02867887 -0.68288810 -0.93872856 #' #> [16] -0.17005783 -0.01754519 -0.83549564 -0.35399612 -1.34878425 #' Created on 2018-08-06 by the [reprex package](http://reprex.tidyverse.org) (v0.2.0). ####### On Sun, 5 Aug 2018, Jinsong Zhao wrote:> Hi there, > > I wrote a function that wraps MASS::boxcox as: > > bc <- function(vec) { > lam <- boxcox(lm(vec ~ 1)) > lam <- lam$x[which.max(lam$y)] > (vec^lam - 1)/lam > } > > When I invoke it as: > >> x <- runif(20) >> bc(x) > Error in eval(predvars, data, env) : object 'vec' not found > > I have googled, and rewrote the above function as: > > bc <- function(vec) { > dat <<- data.frame(vec = vec) > lam <- boxcox(lm(vec ~ 1, dat)) > lam <- lam$x[which.max(lam$y)] > rm(dat, envir = .GlobalEnv) > (vec^lam - 1)/lam > } > > It works. But, I am wondering why MASS::boxcox have to wrap in such way that have to use the data in .GlobalEnv. > > Best, > Jinsong > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >--------------------------------------------------------------------------- Jeff Newmiller The ..... ..... Go Live... DCN:<jdnewmil at dcn.davis.ca.us> Basics: ##.#. ##.#. Live Go... Live: OO#.. Dead: OO#.. Playing Research Engineer (Solar/Batteries O.O#. #.O#. with /Software/Embedded Controllers) .OO#. .OO#. rocks...1k