动态创建函数和表达式 [英] Dynamically creating functions and expressions

查看:25
本文介绍了动态创建函数和表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我当前正在处理一个问题。我正在为一些特定的发行版开发一个包,其中除了其他事情外,我还想创建一个适合某些数据的混合函数。为此,我想使用例如fitdistr函数。问题是,我不知道混合物的分布、重量和组份的数量。因此,我需要一个函数来动态创建某个指定混合物的密度函数,以便fitdistr函数可以使用它。例如,如果用户将调用:

fitmix(data,dist=c(norm,chisq),params=list(c(mean=0,sd=3),df=2),wights=c(0.5,0.5))

要使用ML方法,代码需要创建密度函数

function(x,mean,sd,df) 0.5*dnorm(x,mean,sd)+0.5*dchisq(x,df)

因此可以调用optimfitdistr

一个明显的解决方案是大量使用paste+eval+parse,但我不认为这是最优雅的解决方案。一个很好的解决方案可能隐藏在非标准的计算和表达式操作中,但我在这个问题上没有足够的技能。

附注:参数可以用作优化器的起始值。

推荐答案

使用as.callbquote这样的函数在R中构建表达式相对简单,而函数在R中是第一类对象这一事实要稍微复杂一些。下面是一些可能有帮助的函数的传递

to_params <- function(l) {
    z <- as.list(l)
      setNames(lapply(names(z), function(x) bquote(args[[.(x)]])), names(z))
}

add_exprs <- function(...) {
      x <- list(...)
    Reduce(function(a,b) bquote(.(a) + .(b)), x)
}

get_densities <- function(f) {
    lapply(paste0("d", f), as.name)
}

weight_expr <- function(w, e) {
    bquote(.(w) * .(e))
}
add_params <- function(x, p) {
    as.call(c(as.list(x), p))
}
call_with_x <- function(fn) {
    as.call(list(fn, quote(x)))
} 

fitmix <- function(data, dist, params, weights) {
    fb <- Reduce( add_exprs, Map(function(d, p, w) {
        weight_expr(w, add_params(call_with_x(d), to_params(p)))
    }, get_densities(dist), params, weights))
    f <- function(x, args) {}
    body(f) <- fb
    f
}

请注意,我更改了某些参数的类型。分布应该是字符串。参数应该是命名向量的列表。它可以与如下所示的调用一起工作

ff <- fitmix(data, dist=c("norm","chisq"), params=list(c(mean=0,sd=3),c(df=2)), 
    weights=c(0.5,0.5))
它返回一个接受x和命名参数列表的函数。你可以这样称呼它

ff(0, list(mean=3, sd=2, df=2))
# [1] 0.2823794

返回与

相同的值
x <- 0
0.5 * dnorm(x, mean = 3, sd = 2) + 0.5 * dchisq(x, df = 2)
# [1] 0.2823794

这篇关于动态创建函数和表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆