Metrics
Metrics

Reputation: 15458

Creating a formula (syntax) in R for package

I have a likelihood function that enters as an argument in maxLik function of maxLik package. For example:

library(maxLik) 

likFun <- function(param, x, y, h) {

  dep   <- as.matrix(x[,y])
  indep <- as.matrix(x[,h])
  indep <- as.matrix(cbind(cons=1, indep))
  k     <- dim(indep)[2] 
  beta  <- as.matrix(param[1:k])
  xbeta <- crossprod(t(indep), beta)
  sig   <- param[k+1]
  res   <- (dep-xbeta)/sig
  sum(  (-(1/2)*log(2*pi)) - ((1/2)*log((sig)^2)) - ((res^2)/2)  )

}
model <- maxLik(likFun, start=c(0,0,0,1), grad=NULL, hess=NULL, x=mtcars, 
                y="mpg", h=c("cyl", "hp"))
summary(model)

Basically, the above likelihood function is using maximum likelihood for a multiple regression model. My question is how do I create a formula in R (for the package) like in lm so that the user would be able to enter the dependent variable and independent variables and data. I have checked model.matrix but I am not sure whether it is the one I should be looking for. Any suggestion in this regard would be highly appreciated.

Upvotes: 4

Views: 258

Answers (2)

Ferdinand.kraft
Ferdinand.kraft

Reputation: 12819

To be able to call your function using something like mpg ~ cyl + hp instead of y="mpg", h=c("cyl", "hp") in the arguments, you can use a formula object. They are unevaluated by default, so you don't need substitute nor match.call.

If you want something more complex than simply stripping out the symbols in each side of the formula, you'll have to write your own parser. Otherwise, use function all.vars:

f <- function(data, formula){
    print("Right hand side:")
    print(head(data[,all.vars(formula[[3]]), drop=FALSE]))
    print("Left hand side:")
    print(head(data[,all.vars(formula[[2]]), drop=FALSE]))
}

Result:

> f(mtcars, mpg ~ cyl + hp)
[1] "Right hand side:"
                  cyl  hp
Mazda RX4           6 110
Mazda RX4 Wag       6 110
Datsun 710          4  93
Hornet 4 Drive      6 110
Hornet Sportabout   8 175
Valiant             6 105
[1] "Left hand side:"
                   mpg
Mazda RX4         21.0
Mazda RX4 Wag     21.0
Datsun 710        22.8
Hornet 4 Drive    21.4
Hornet Sportabout 18.7
Valiant           18.1

Upvotes: 3

Konrad Rudolph
Konrad Rudolph

Reputation: 545588

Roughly, you use eval inside the function. However, you first need to get your function arguments in an unevaluated context (so that you can substitute the variables into the formula). To do this, you’d need match.call. Here’s a very basic example:

f <- function (.FUN, ...) {
    args <- match.call(expand.dots = FALSE)
    eval(args$.FUN, args$...)
}

This will capture the formula in .FUN and the actual arguments in ..., which can be accessed (as a list) via args$....

Now you can call that function similar to lm:

> f(x + y, x = 1, y = 2)
3

As an alternative to match.call, you could also use substitute to get a function argument in an unevaluated context:

f <- function (.FUN, ...)
    eval(substitute(.FUN), list(...))

Upvotes: 2

Related Questions