针对beta二项分布优化负日志总和中的alpha和beta

时间:2015-09-30 15:49:08

标签: r for-loop sum

我尝试使用我的数据集中的变量创建sigma / summation函数,如下所示:

paste0("(choose(",zipdistrib$Leads[1],",",zipdistrib$Starts[1],")*beta(a+",zipdistrib$Starts[1],",b+",zipdistrib$Leads[1],"-",zipdistrib$Starts[1],")/beta(a,b))")

当我输入该代码时,我得到了

[1] "(choose(9,6)*beta(a+6,b+9-6)/beta(a,b))"

我想创建一个sigma / summation函数,其中ab是未知的自由浮动变量,Leads[i]Starts[i]的值由值决定我的数据集中的LeadsStarts用于观察i。我尝试将sum函数与mapplysapply结合使用无效。目前,我正在使用for循环结合paste0命令将函数创建为字符串,以便更改的唯一内容是变量Leads的值和Starts。然后,我尝试将结果强制转换为函数。令我惊讶的是,我实际上可以在不创建语法错误的情况下输入此代码,但是当我尝试优化变量ab的函数时,我没有成功。

这是我尝试用字符串创建函数。

betafcn <- function (a,b) {
abfcnstring <- 
  for (i in 1:length(zipdistrib$Zip5))
    toString(
      paste0("      (choose(",zipdistrib$Leads[i],",",zipdistrib$Starts[i],")*beta(a+",zipdistrib$Starts[i],",b+",zipdistrib$Leads[i],"-",zipdistrib$Starts[i],")/beta(a,b))+")
   )
as.function(
  as.list(
    substr(abfcnstring, 1, nchar(abfcnstring)-1) 
  )
)
}

然后,当我尝试优化a和b的功能时,我得到以下结果:

optim(c(a=.03, b=100), betafcn(a,b))
## Error in as.function.default(x, envir) : 
  argument must have length at least 1

我是否有更好的方法可以使用sigmai=1或其他mapply功能将lapply*apply编译为数据集长度?还是我坚持使用可怕的for循环?然后,一旦我创建了该功能,我该如何确保我可以优化ab

更新

这就是我的数据集的样子:

leads <-c(7,4,2)
sales <-c(3,1,0)
zipcodes <-factor(c("11111", "22222", "33333"))
zipleads <-data.frame(ZipCode=zipcodes, Leads=leads, Sales=sales)
zipleads
##  ZipCode Leads Sales
# 1   11111     7     3
# 2   22222     4     1
# 3   33333     2     0

我的目标是创建一个看起来像这样的函数:

betafcn <-function (a,b) {
   (choose(7,3)*beta(a+3,b+7-3)/beta(a,b))+
   (choose(4,1)*beta(a+4,b+4-1)/beta(a,b))+
   (choose(2,0)*beta(a+0,b+2-0)/beta(a,b))
  }

不同之处在于,我最好将数据集值替换为潜在客户和销售的任何其他可能的矢量。

2 个答案:

答案 0 :(得分:3)

由于R默认情况下会对其大多数操作进行矢量化,因此您可以根据ab的单个值(它将自动循环到数据的长度)和向量来编写表达式xy(即LeadsSales);如果您在日志范围内进行计算,则可以使用sum()(而不是prod())来组合结果。因此,我认为你正在寻找类似的东西:

betafcn <- function(a,b,x,y,log=FALSE) {
   r <- lchoose(x,y)+lbeta(a+x,b+x-y)-lbeta(a,b)
   if (log) r else exp(r)
}

请注意,(1)optim() 默认情况下最小化(2)如果您正在尝试优化可能性,那么您最好优化对数似然... < / p>

由于所有内部函数(+lchooselbeta)都是矢量化的,因此您应该能够通过以下方式在整个数据集中应用它:

zipleads <- data.frame(Leads=c(7,4,2),Sales=c(3,1,0))
objfun <- function(p) {  ## negative log-likelihood
    -sum(betafcn(p[1],p[2],zipleads$Leads,zipleads$Sales,
         log=TRUE))
}
objfun(c(1,1))
optim(fn=objfun,par=c(1,1))

我为这个例子得到了疯狂的答案(两个形状参数的值非常大),但我认为这是因为将双参数模型拟合到三个数据点非常困难!

由于beta-binomial的形状参数(看起来似乎是这样)必须是正的,因此您可能会遇到无约束优化的问题。您可以使用method="L-BFGS-B", lower=c(0,0)或优化日志范围内的参数...

答案 1 :(得分:1)

我认为你的例子绝对是复杂的。如果您要通过粘贴字符值来尝试创建函数,首先需要理解如何使函数体具有未评估的表达式,并且在理解了基本任务之后,您可以详细说明。 ..如果事实上有必要,请注意BenBolker的建议。

choosefcn <- function (a,b) {}
txtxpr <- paste0("choose(",9,",",6,")" )
body(choosefcn) <- parse(text= txtxpr)
#----------
> betafcn
function (a, b) 
choose(9, 6)

val1 <- "a"
val2 <- "b"
txtxpr <- paste0("choose(", val1, ",", val2, ")" )
body(choosefcn) <- parse(text= txtxpr)
#
choosefcn 
#function (a, b) 
#choose(a, b)

也可以使用formals<-函数单独配置形式参数。请参阅以下每个帮助页面:

?formals
?body
?'function'   # needs to be quoted