[R] "nested" getInitial calls; variable scoping problems: Solved??

Keith Jewell k.jewell at campden.co.uk
Tue Aug 19 12:12:19 CEST 2008


Hi All,

I've found a solution to my problems which I think is optimal, but I've been 
wrong before (!!) so comments are welcome.

To avoid scoping problems in the 'inner' getInitial I modify the formula so 
that all variable values are specified explitly in the formula, the inner 
getInitial need not search for any values so there are no scoping problems:
-----------------------
ssA <- selfStart(
  model = function(x, Coeff, A)
    {
    paste(x, Coeff, A)
    },
  initial = function(mCall, data, LHS)
    {
    x <- eval(mCall[["x"]], data, parent.frame())
    A <- eval(mCall[["A"]], data, parent.frame())
    paste("CoeffA", x, A)
    },
  parameters = c("Coeff")
               )
ssB <- selfStart(
  model = function(x, Coeff, A)
    {
    paste(x, Coeff, A)
    },
  initial = function(mCall, data, LHS)
    {
    A <- eval(mCall[["A"]], data, parent.frame())
    Amod <- paste(A, "mod in B")
#-----------------------------------
# Doing a getInitial for (for example)  y' ~ ssA(x, Coeff, Amod)
# to avoid scoping problems, specify values in the formula for LHS and
# all ssA arguments except Coeff; i.e. all except attr(ssA, "pnames")
#------------------------------------------------------
    object <- y ~ ssA(x, Coeff, A)    # define a formula object
    object[[2]] <- eval(LHS, data, parent.frame())    # left hand side 
values
# name RHS arguments by match.call, then assign values  to x and A
    object[[3]] <- match.call(get(as.character(object[[3]][[1]])), 
object[[3]])
    object[[3]]$x <-  as.character(eval(mCall[["x"]], data, parent.frame())) 
# x
    object[[3]]$A <-  Amod                                      # A
    getInitial(object, data) # do the getInitial
     },
  parameters = c("Coeff")
                 )
getInitial(y ~ ssA("this", "that", "other"), data= data.frame(x=c("test"), 
y=1))
getInitial(y ~ ssB("this", "that", "other"), data= data.frame(x=c("test"), 
y=1))
getInitial(y ~ ssB(x, "that", "other"), data= data.frame(x=c("test1", 
"test2"), y=1:2))
------------------

Hope that helps someone,

Keith Jewell

"Keith Jewell" <k.jewell at campden.co.uk> wrote in message 
news:g8bnlj$tkm$1 at ger.gmane.org...
> Hi All,
>
> Another nls related problem (for background, I'm migrating a complicated 
> modelling package from S-plus to R).
>
> Below I've reduced this to the minimum necessary to demonstrate my problem 
> (I think); the real situation is more complicated.
>
> Two similar selfStart functions, ssA and ssB.
> The 'initial' function for ssB modifies its arguments a little and then 
> calls getInital for ssA.
> In addition to the "x" and the fitted coefficients ("Coeff"), ssA and ssB 
> have arguments ("A") which are not the same length as the dataframe, so 
> cannot be passed as columns of that dataframe.
>
> The initial function for ssA uses eval(... parent.frame()) to find "A", 
> which is fine when called from .GlobalEnv. But when called from the 
> initial function of ssB it can't find (the modified version of) "A" .
>
> If A is assigned as a parameter of the dataframe then getInitial.formula 
> returns "A" as initial estimates of "Coeff", so that doesn't work.
> I've explored the evaluation frame parent-child structure created by the 
> nested getInitial calls, but it doesn't seem helpful, and I certainly 
> couldn't trust my understanding of it.
> I'm considering making up the matched call and calling the 'initial' 
> function of ssA directly, in the same manner as getInitial.selfStart
>    attr(ssA, "initial"))(mCall = mCall, data = data, LHS = LHS)
> or perhaps if I call getInitial thus...
>    getInitial(ssA, data, mCall, LHS = NULL, ...)
> it will call getInitial.selfStart without calling getInitial.formula.
> In that case perhaps eval(... parent.frame())  will find the argument?
> Or, at least I could attach the argument to the dataframe as a parameter.
>
> But this all seems a but clumsy, and I feel there must be a better way. 
> Any comments and/or advice will be welcome.
>
> Thanks in advance;
>
> Keith Jewell
> -------------------------------------------
> code showing the problem:
> ssA <- selfStart(
>  model = function(x, Coeff, A)
>    {
>    paste(x, Coeff, A)
>    },
>  initial = function(mCall, data, LHS)
>    {
>    x <- eval(mCall[["x"]], data, parent.frame())
>    A <- eval(mCall[["A"]], data, parent.frame())
>    paste("CoeffA", x, A)
>    },
>  parameters = c("Coeff")
>               )
> ssB <- selfStart(
>  model = function(x, Coeff, A)
>    {
>    paste(x, Coeff, A)
>    },
>  initial = function(mCall, data, LHS)
>    {
>    x <- eval(mCall[["x"]], data, parent.frame())
>    A <- eval(mCall[["A"]], data, parent.frame())
>    Amod <- paste(A, "mod in B")
>    getInitial(y ~ ssA(x, Coeff, Amod), data)
>    },
>  parameters = c("Coeff")
>                 )
> getInitial(y ~ ssA("this", "that", "other"), data= 
> data.frame(x=c("test")))
> getInitial(y ~ ssB("this", "that", "other"), data= 
> data.frame(x=c("test")))
> ---------------------------
>> sessionInfo()
> R version 2.7.1 Patched (2008-08-15 r46352)
> i386-pc-mingw32
>
> locale:
> LC_COLLATE=English_United Kingdom.1252;LC_CTYPE=English_United 
> Kingdom.1252;LC_MONETARY=English_United 
> Kingdom.1252;LC_NUMERIC=C;LC_TIME=English_United Kingdom.1252
>
> attached base packages:
> [1] stats     graphics  grDevices utils     datasets  methods   base
>
> ______________________________________________
> R-help at r-project.org mailing list
> 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.
>



More information about the R-help mailing list