[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