Reputation: 15458
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
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
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