Skip to content

g parameter for deltaMethod() as a function

6 messages · John Fox, Marc Girondot

#
Hi everyone,

I try to use the Default S3 method DeltaMethod() from car package, but I 
have some problems when I try to use a function as the "g" parameter. I 
don't know if it is possible anyway. I hope that you could tell me:

Here an example from the help of deltaMethod(). It works and I 
understand well (I think at least !).

library(car)
m1 <- lm(time ~ t1 + t2, data = Transact)
deltaMethod(coef(m1), "t1/t2", vcov.=vcov(m1))

###############

I would like do the same with a function instead of "t1/t2":

try_g <- function(...) {
   par <- list(...)
   return(par$t1/par$t2)
}

try_g(t1=1, t2=2)
deltaMethod(coef(m1), "try_g", vcov.=vcov(m1))

But I get an error:

Error in as.data.frame.default(x[[i]], optional = TRUE) :
   cannot coerce class ""function"" to a data.frame

If someone could give me the solution... or tell me if it is impossible !

Thanks

Marc

PS. In fine I would like using deltaMethod() to produce a confidence 
interval after fitting a model using ML with optim.
#
Dear Marc,
I don't see how that would work. From ?deltaMethod: "g [the second argument]: A quoted string that is the function of the parameter estimates to be evaluated; see the details below."

A possible solution would be to write a wrapper function that prepares a proper call to deltaMethod().

I hope this helps,
 John

--------------------------------------
John Fox, Professor
McMaster University
Hamilton, Ontario, Canada
Web: socserv.mcmaster.ca/jfox
#
Le 30/01/2017 ? 19:04, Fox, John a ?crit :
Hi John,

This is exactly what I try to do: a wrapper (I forget that name in 
English !).

I have made some progress to do a wrapper function:

try_g <- function(...) {
   par <- list(...)
   return(par$t1/par$t2)
}

try_g(t1=1, t2=2)
deltaMethod(coef(m1), "try_g(t1, t2)", vcov.=vcov(m1))

The wrapper function try_g is accepted now, but I get an error because 
deltaMethod() tried to do symbolic derivative:

 > deltaMethod(coef(m1), "try_g(t1, t2)", vcov.=vcov(m1))
Error in D(g, names(para)[i]) :
   La fonction 'try_g' n'est pas dans la table des d?riv?es 
(translation: The function 'try_g' is not in the table of derivative 
functions).

I was hopping that numeric approximation of derivative (example 
numDeriv::grad() or deriv() ) could be used, but it is not the case.

Thanks

Marc
#
Dear Marc,

A "wrapper function" *calls* deltaMethod(). Your function try_g() is intended to be *called by* try_g(). Actually, you just pass to deltaMethod() a character string that would evaluate to the function call, and deltaMethod() doesn't know what to do with that.

The description of the g (second) argument in ?deltaMethod seems perfectly clear to me; beyond what I quoted, in "Details" you'll find, "The argument g must be a quoted character string that gives the function [of the coefficients] of interest. For example, if you set m2 <- lm(Y ~ X1 + X2 + X1:X2), then deltaMethod(m2,"X1/X2") applies the delta method to the ratio of the coefficient estimates for X1 and X2. The argument g can consist of constants and names associated with the elements of the vector of coefficient estimates. Etc."

Try writing a function that calls deltaMethod() and does what you want.

John
#
Dear Mark,

I realized that there was a typo in my last response, which is corrected below:
Actually this should say, "Your function try_g() is intended to be *called by* deltaMethod().?

Sorry if that was confusing,
 John
#
Dear John and list members,

I have found a solution using the package nlWaldTest. I post the 
solution in case someone else will have this problem.

Here is a summary of the problem:
I would like use the delta method for a function for which no derivative 
using D() can be calculated. I would like rather use numerical derivative.

Here is the solution. In the two first examples, symbolic derivative is 
used.

library(car)
m1 <- lm(time ~ t1 + t2, data = Transact)
deltaMethod(coef(m1), "t1/t2", vcov.=vcov(m1))

library("nlWaldTest")
nlConfint(obj = NULL, texts="b[2]/b[3]", level = 0.95, coeff = coef(m1),
           Vcov = vcov(m1), df2 = TRUE, x = NULL)

############# Now numerical derivative is used. The result is the same.

try_g <- function(...) {
   par <- list(...)
   return(par[[1]]/par[[2]])
}

nlConfint(obj = NULL, texts="try_g(b[2], b[3])", level = 0.95, coeff = 
coef(m1),
           Vcov = vcov(m1), df2 = TRUE, x = NULL)

Marc