[R] Delta method using numerical derivatives

Mark Clements Mark.Clements at anu.edu.au
Tue Feb 15 22:49:46 CET 2011


Dear all,

Is there a fairly general R implementation of the delta method that uses
numerical derivatives? 

I realise that the delta method has been implemented using symbolic
derivatives (e.g. alr3::delta.method, emdbook::deltamethod,
msm::deltamethod and survey:::nlcon), however possibly non-linear
estimators using the delta method with numerical derivatives can be
quite useful (e.g. predictnl in Stata and the estimate and predict
statements for proc nlmixed in SAS).

I would like something akin to the following predictnl() function:

## get some data and fit a model 
require(Epi)
data(lungDK)
fit <- glm(D/Y ~ as.factor(A5)+as.factor(A5):P5-1,
           data=lungDK, subset=(P5>=1970), weight=Y,
           family=poisson("identity")) # (Hakulinen and Dyba)
## calculate some summary statistics (e.g. cumulative incidence to 85
years)
require(plyr)
cuminc <- function(object,year=P5,newdata=NULL)
  ddply(newdata,deparse(substitute(year)),function(data)
        sum(5*predict(object,newdata=data)))[,-1,drop=TRUE]
## Now: get summary statistics and SEs using the delta method
predictnl(fit,cuminc,newdata=subset(lungDK,A5<85 & P5>=1970))


My first attempt is below, which depends on the coef() and vcov()
functions and object$coefficients. The approach seems obvious, so I
expect that this has been done before.

Kindly, Mark.


## numerically calculate the gradient (func may return a vector)
grad <- function(func,x,...) # would shadow numDeriv::grad()
  {
    h <- .Machine$double.eps^(1/3)*ifelse(abs(x)>1,abs(x),1)
    temp <- x+h
    h.hi <- temp-x
    temp <- x-h
    h.lo <- x-temp
    twoeps <- h.hi+h.lo
    nx <- length(x)
    ny <- length(func(x,...))
    if (ny==0L) stop("Length of function equals 0")
    df <- if(ny==1L) rep(NA, nx) else matrix(NA, nrow=nx,ncol=ny)
    for (i in 1L:nx) {
      hi <- lo <- x
      hi[i] <- x[i] + h.hi[i]
      lo[i] <- x[i] - h.lo[i]
      if (ny==1L)
        df[i] <- (func(hi, ...) - func(lo, ...))/twoeps[i]
      else df[i,] <- (func(hi, ...) - func(lo, ...))/twoeps[i]
      }
    return(df)
  }
## fun: takes coef as its first argument
## requires: coef() and vcov() on the object
numDeltaMethod <- function(object,fun,...) {
  coef <- coef(object)
  est <- fun(coef,...)
  Sigma <- vcov(object)
  gd <- grad(fun,coef,...)
  se.est <- as.vector(sqrt(diag(t(gd) %*% Sigma %*% gd)))
  data.frame(Estimate = est, SE = se.est)
}
predictnl <- function (object, ...) 
  UseMethod("predictnl")
predictnl.default <- function(object,fun,newdata=NULL,...)
  {
    if (is.null(newdata) && !is.null(object$data))
      newdata <- object$data
    localf <- function(coef,...)
      {
        object$coefficients = coef
        fun(object,...)
      }
    numDeltaMethod(object,localf,newdata=newdata,...)
  }



More information about the R-help mailing list