I've narrowed my scope problems with predict.coxph further. Here is a condensed example: fcall3 <- as.formula("time ~ age") dfun3 <- function(dcall) { fit <- lm(dcall, data=lung, model=FALSE) model.frame(fit) } dfun3(fcall3) The final call fails: it can't find 'dcall'. The relevant code in model.frame.lm is: env <- environment(formula$terms) if (is.null(env)) env <- parent.frame() eval(fcall, env, parent.frame()) If the environment of the formula is .Globalenv, as it is here, the contents of parent.frame() are ignored. Adding a print(ls(parent.frame())) statement just above the final call shows that it isn't a scope issue: the variables we want are there. I don't understand the logic behind looking for variables in the place the formula was first typed (this is not a complaint). The inability to look elsewhere however has stymied my efforts to fix the scoping problem in predict.coxph, unless I drop the env(formula) argument alltogether. But I assume there must be good reasons for it's inclusion and am reluctant to do so. Terry Therneau> sessionInfo()R version 2.13.0 RC (2011-04-12 r55424) Platform: x86_64-unknown-linux-gnu (64-bit) locale: [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C [3] LC_TIME=en_US.UTF-8 LC_COLLATE=C [5] LC_MONETARY=C LC_MESSAGES=en_US.UTF-8 [7] LC_PAPER=en_US.UTF-8 LC_NAME=C [9] LC_ADDRESS=C LC_TELEPHONE=C [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C attached base packages: [1] stats graphics grDevices utils datasets methods base PS. This also fails dfun3 <- function(dcall) { fit <- lm(dcall, data=lung) model.frame(fit, subset=1:10) } You just need to force model.frame.lm to recreate data.
On 11-04-18 5:51 PM, Terry Therneau wrote:> I've narrowed my scope problems with predict.coxph further. > Here is a condensed example: > > fcall3<- as.formula("time ~ age") > dfun3<- function(dcall) { > fit<- lm(dcall, data=lung, model=FALSE) > model.frame(fit) > } > dfun3(fcall3) > > The final call fails: it can't find 'dcall'. > > The relevant code in model.frame.lm is: > env<- environment(formula$terms) > if (is.null(env)) > env<- parent.frame() > eval(fcall, env, parent.frame()) > > If the environment of the formula is .Globalenv, as it is here, the > contents of parent.frame() are ignored. Adding a > print(ls(parent.frame())) > statement just above the final call shows that it isn't a scope issue: > the variables we want are there. > > I don't understand the logic behind looking for variables in the place > the formula was first typed (this is not a complaint). The inability to > look elsewhere however has stymied my efforts to fix the scoping problem > in predict.coxph, unless I drop the env(formula) argument alltogether. > But I assume there must be good reasons for it's inclusion and am > reluctant to do so.The reason is that when a formula is created, the variables in it are assumed to have meaning in that context. Where you work with the formula after that should not be relevant: that's why formulas carry environments with them. When you create the formula before the variables, things go wrong. There's probably a way to associate the lung dataframe with the formula, or create the formula in such a way that things work, but I can't spot it. Duncan Murdoch> Terry Therneau > >> sessionInfo() > R version 2.13.0 RC (2011-04-12 r55424) > Platform: x86_64-unknown-linux-gnu (64-bit) > > locale: > [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C > [3] LC_TIME=en_US.UTF-8 LC_COLLATE=C > [5] LC_MONETARY=C LC_MESSAGES=en_US.UTF-8 > [7] LC_PAPER=en_US.UTF-8 LC_NAME=C > [9] LC_ADDRESS=C LC_TELEPHONE=C > [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C > > attached base packages: > [1] stats graphics grDevices utils datasets methods > base > > PS. This also fails > dfun3<- function(dcall) { > fit<- lm(dcall, data=lung) > model.frame(fit, subset=1:10) > } > You just need to force model.frame.lm to recreate data. > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel
On Mon, Apr 18, 2011 at 5:51 PM, Terry Therneau <therneau at mayo.edu> wrote:> I've narrowed my scope problems with predict.coxph further. > Here is a condensed example: > > fcall3 <- as.formula("time ~ age") > dfun3 <- function(dcall) { > ? ?fit <- lm(dcall, data=lung, model=FALSE) > ? ?model.frame(fit) > } > dfun3(fcall3) > > The final call fails: it can't find 'dcall'. > > The relevant code in model.frame.lm is: > ? ? ? env <- environment(formula$terms) > ? ? ? if (is.null(env)) > ? ? ? ? ? ?env <- parent.frame() > ? ? ? ?eval(fcall, env, parent.frame()) > > If the environment of the formula is .Globalenv, as it is here, the > contents of parent.frame() are ignored. ?Adding a > ? ? ? ? ? print(ls(parent.frame())) > statement just above the ?final call shows that it isn't a scope issue: > the variables we want are there. > > ?I don't understand the logic behind looking for variables in the place > the formula was first typed (this is not a complaint). ?The inability to > look elsewhere however has stymied my efforts to fix the scoping problem > in predict.coxph, unless I drop the env(formula) argument alltogether. > But I assume there must be good reasons for it's inclusion and am > reluctant to do so. >Try using do.call. Using the built in BOD to illustrate, we first try the posted code to view the error:> fcall3 <- as.formula("demand ~ Time") > dfun3 <- function(dcall) {+ fit <- lm(dcall, data=BOD, model=FALSE) + model.frame(fit) + }> dfun3(fcall3)Error in model.frame(formula = dcall, data = BOD, drop.unused.levels = TRUE) : object 'dcall' not found> > # now replace the lm call with a do.call("lm" ...) > # so that dcall gets substituted before the call to lm: > > fcall3 <- as.formula("demand ~ Time") > dfun3 <- function(dcall) {+ fit <- do.call("lm", list(dcall, data = BOD, model = FALSE)) + model.frame(fit) + }> dfun3(fcall3)demand Time 1 8.3 1 2 10.3 2 3 19.0 3 4 16.0 4 5 15.6 5 6 19.8 7 -- Statistics & Software Consulting GKX Group, GKX Associates Inc. tel: 1-877-GKX-GROUP email: ggrothendieck at gmail.com