Skip to content

Trouble embedding functions (e.g., deltaMethod) in other functions

5 messages · jim holtman, PatGauthier, Blaser Nello +1 more

#
Dear R community, 

I've been writing simple functions for the past year and half and have come
across a similar problem several times. The execution of a function within
my own function produces NaN's or fails to execute as intended. My conundrum
is that I can execute the function outside of my function without error, so
it's difficult for me, as a novice functioneer, to figure out what's going
wrong. 

Here's my example for deltaMethod(): 

t <- c(0.00000, 26.24551, 61.78180, 86.88254, 221.75480)
m <- c(48.591707, 15.655895, 12.284635, 5.758547, 0.000000)
dat <- data.frame(t = t, m = m)
m0 <- m[1]
t0 <- t[5]
nlls <- nls(m ~ (m0^(1/lambda) - (t * m0/t0)^(1/lambda))^lambda, 
    start = list(lambda = 1), data = dat)
xVal <- seq(0, t0, length = 10)
mod.SE <- list()
for(i in 1:length(xVal)){
	z <- xVal[i]
	mod.SE[[i]] <- deltaMethod(nlls, "(m0^(1/lambda) - (z *
m0/t0)^(1/lambda))^lambda")$SE
}
mod.SE

This code executes deltaMethod() flawlessly (NOTE: [[1]] and [[10]] are
supposed to be NaN's). However, my goal is to embed the deltaMethod inside
another function I'm writing. For brevity's sake, here's a very simple
example that produces the same problem.

deltaSE <- function(mod, x){	
	mod.SE <- list()
	for(i in 1:length(xVal)){
		z <- xVal[i]
		mod.SE[[i]] <- deltaMethod(mod, "(m0^(1/lambda) - (z *
m0/t0)^(1/lambda))^lambda")$SE
	}
	mod.SE
}
deltaSE(nlls, xVal)

deltaMethod, when embedded in my deltaSE function produces only NaN's.  When
I debug(deltaSE) and debug(deltaMethod), and then debug(deltaMethod.default)
once delta method is debugging within deltaSE, I can see that eval() is
producing a value of 0 for the estimate value of m. An m of 0 indeed would
produce an NaN. I'm just not sure why this function is performing
differently inside and outside my function. 

Any help for a lowly functioneer would be great!
Patrick



--
View this message in context: http://r.789695.n4.nabble.com/Trouble-embedding-functions-e-g-deltaMethod-in-other-functions-tp4662178.html
Sent from the R help mailing list archive at Nabble.com.
#
Instead of NaN's, I get the error message: Error in eval(expr, envir, enclos) : object 'z' not found. The reason you get the NaN's is, because you defined z in your global environment. The deltaMethod doesn't find the z defined in your function. I don't know why or how to fix this. Somebody with more R experience could probably do this. But if you look at the source code of deltaMethod you can solve the problem in your specific case with these function.

deltaMethod2 <- function(object, g, vcov., z, ...){
  if (!is.character(g)) 
    stop("The argument 'g' must be a character string")
  if ((car:::exists.method("coef", object, default = FALSE) || (!is.atomic(object) && 
    !is.null(object$coefficients))) && car:::exists.method("vcov", 
                                                     object, default = FALSE)) {
    if (missing(vcov.)) 
      vcov. <- vcov(object)
    object <- coef(object)
  }
  para <- object
  para.names <- names(para)
  g <- parse(text = g)
  q <- length(para)
  for (i in 1:q) {
    assign(names(para)[i], para[i])
  }
  est <- eval(g)
  names(est) <- NULL
  gd <- rep(0, q)
  for (i in 1:q) {
    gd[i] <- eval(D(g, names(para)[i]))
  }
  se.est <- as.vector(sqrt(t(gd) %*% vcov. %*% gd))
  data.frame(Estimate = est, SE = se.est)
}
deltaSE <- function(mod, x){
  mod.SE <- list()
  for(i in 1:length(x)){
    z <- x[i]
    mod.SE[[i]] <- deltaMethod2(mod, g="(m0^(1/lambda) - (z * m0/t0)^(1/lambda))^lambda", z=z)$SE
  }
  mod.SE
}
deltaSE(nlls, xVal)


-----Original Message-----
From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf Of PatGauthier
Sent: Freitag, 22. M?rz 2013 13:54
To: r-help at r-project.org
Subject: Re: [R] Trouble embedding functions (e.g., deltaMethod) in other functions

Ah Yes, good point. However, it still does not correct the situation. I still get NaN's. 



--
View this message in context: http://r.789695.n4.nabble.com/Trouble-embedding-functions-e-g-deltaMethod-in-other-functions-tp4662178p4662187.html
Sent from the R help mailing list archive at Nabble.com.

______________________________________________
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.
#
Dear Blaser and Pat,

I missed the original posting because "deltaMethod" appears near the end of
the message subject and was truncated by my email reader.

The problem is caused by lexical scoping. That is, deltaMethod(), which is
in the car namespace, will see objects in the global environment, but not in
the environment of your function -- you're proceeding as if R used dynamic
scoping.

Here's another solution, which also cleans up some other problems in your
function, is more general, and doesn't depend on variables in the global
environment:

deltaSE <- function(mod, x, func, ...){
    constants <- c(...)
    for (i in seq_along(constants)) assign(names(constants[i]),
constants[i])
    myDelta <- car:::deltaMethod.default
    exists.method <- car:::exists.method
    environment(myDelta) <- environment()
    b <- coef(mod)
    V <- vcov(mod)
    mod.SE <- vector(length(x), mode="list")
    for(i in 1:length(x)){
        z <- x[i]
        mod.SE[[i]] <- myDelta(b, func, vcov.=V, ...)$SE
    }
    mod.SE
}
unlist(deltaSE(nlls, xVal, "(mm0^(1/lambda) - (z *
mm0/tt0)^(1/lambda))^lambda", mm0=m0, tt0=t0))

Maybe this approach can be adapted to make deltaMethod() in car more
flexible.

I hope this helps,
 John