如何根据data.frame列(R)定义函数参数?

时间:2016-02-16 09:13:49

标签: r function

我有一个运行线性模型最大似然估计的脚本。该模型有几个变量,我需要偶尔改变它们,可能添加或删除一些。定义似然函数的常用方法是这样的:

LL <- function(beta0, beta1, beta2, mu, sigma){
   R = y - beta0*X$x0 + beta1*X$x1 + beta2*X$x2
   R = dnorm(R, mu, sigma, log = T)
   -sum(R)
} 

我在向量y中有因变量,在data.frame X中有协变量:

X <- data.frame(x0 = 1, x1 = runif(100), x2 = runif(100)*2)
y <- X$x0 + X$x1 + X$x2 + rnorm(100)

现在变量的数量可能会因应用程序的变化而变化,我需要重新构造函数,以便它将采用与data.frame X中的列一样多的协变量。我已经能够将此重新表述为更多一般形式:

cols <- 0:(ncol(X)-1)
betas <- paste0("beta", cols)
eqR <- paste0("y - ", paste0(betas, "*X$x", cols, collapse = " - "))

LL <- function(beta0, beta1, beta2, mu, sigma){
   R = as.formula(eqR)
   R = dnorm(R, mu, sigma, log = T)
   -sum(R)
}

我仍然在努力寻找一种动态定义函数的方法,这样它就可以获得与协变量矩阵中的列相同数量的beta参数。省略号在这里可能有用吗?我也试过了do.call

LL <- function(betas, mu, sigma){
   R <- do.call(dnorm(as.formula(eqR), mu, sigma, log = T), betas)
   -sum(R)
}

当您适合模型时,这不起作用,模型在初始值列表中有另一个绊脚石:

require(stats4)
fit <- mle(LL, start = list(beta0 = 0, beta1 = 0, beta2 = 0, mu = 0, sigma = 1))

对此有何想法?

编辑:

我使用bbmle包进行了一些改进:

require(bbmle)

dfModel <- cbind(y, X)
cols <- 0:(ncol(X)-1)
betas <-paste0("beta",cols)

betaList <- as.list(rep(0), length(betas)))
names(betaList) <- betas
initList <- c(betaList, mu = 0, sigma = 1)

fitML <- mle2(mu ~ dnorm(mean = y - beta0*x0 - beta1*x1 - beta2*x2, sd = sigma),
              start = initList,
              data = dfModel)

以上示例有效。但是当我尝试使用as.formula预先定义函数时,我无法使其正常工作。所以以下内容不起作用。

eqR <- paste0("y - ", paste0(betas, "*x", cols, collapse = " - "))

fitML <- mle2(mu ~ dnorm(mean = as.formula(eqR), sd = sigma),
              start = initList,
              data = dfModel)

错误消息是:

  

eval(expr,envir,enclos)中的错误:找不到对象'beta0'

我怀疑这可能与范围有关 - dnorm和as.formula之间的冲突?我找不到相应的解决方法。

1 个答案:

答案 0 :(得分:0)

试试这个:

betas = c(0,0,0)
X <- data.frame(x0 = 1, x1 = runif(100), x2 = runif(100)*2)
y <- apply(X,1,sum) + rnorm(100)

其中betas是(b0,b1,b2,...等),其长度必须等于X的列数。
由于X可以具有不同数量的列y,因此应如上定义。

您的LL功能应更改为:

LL <- function(betas, mu, sigma){

    R = y - as.matrix(X) %*% as.matrix(betas)

    R = dnorm(R, mu, sigma, log = T)
    -sum(R)
}

其中%*%是矩阵乘积。这与执行b[1]*X[,1] + b[2]*X[,2] + b[3]*X[,3] + ... + b[n]*X[,n]

相同

通过这些更改,您可以拥有包含任意数量列的数据框Xbetas一个与X列相同长度的数组。

我希望我明白你的需要。