我尝试使用我的数据集中的变量创建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函数,其中a
和b
是未知的自由浮动变量,Leads[i]
和Starts[i]
的值由值决定我的数据集中的Leads
和Starts
用于观察i
。我尝试将sum
函数与mapply
和sapply
结合使用无效。目前,我正在使用for
循环结合paste0
命令将函数创建为字符串,以便更改的唯一内容是变量Leads
的值和Starts
。然后,我尝试将结果强制转换为函数。令我惊讶的是,我实际上可以在不创建语法错误的情况下输入此代码,但是当我尝试优化变量a
和b
的函数时,我没有成功。
这是我尝试用字符串创建函数。
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
我是否有更好的方法可以使用sigma
或i=1
或其他mapply
功能将lapply
从*apply
编译为数据集长度?还是我坚持使用可怕的for
循环?然后,一旦我创建了该功能,我该如何确保我可以优化a
和b
?
更新
这就是我的数据集的样子:
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))
}
不同之处在于,我最好将数据集值替换为潜在客户和销售的任何其他可能的矢量。
答案 0 :(得分:3)
由于R默认情况下会对其大多数操作进行矢量化,因此您可以根据a
和b
的单个值(它将自动循环到数据的长度)和向量来编写表达式x
和y
(即Leads
和Sales
);如果您在日志范围内进行计算,则可以使用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>
由于所有内部函数(+
,lchoose
,lbeta
)都是矢量化的,因此您应该能够通过以下方式在整个数据集中应用它:
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