2017-02-21 93 views
1

我目前正在處理一個問題。我正在爲一些特定發行版打包,其中我希望創建一個適合某些數據的函數。爲此,我想使用例如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但我不認爲這是最優雅的解決方案。一個很好的解決方案可能隱藏在非標準評估和表達式操縱的某個地方,但我在這個問題上沒有足夠的技巧。

P.S.參數可以用作優化器的起始值。

+0

你有沒有嘗試什麼嗎?這基本上就像是一個「請爲我編碼」這個問題,在本網站不鼓勵。如果您可以提出更具體的問題或至少顯示您嘗試過的代碼,那可以改善您的問題。 – MrFlick

+0

這個例子是真實任務的簡化版本,所以我的代碼對這個問題沒有幫助。我可以使用lapply(seq_along(D),function(i)paste(dist [i],paste(「(x,」,paste(names(params [[i]))粘貼來創建調用,崩潰=「,」),「)」,sep =「」),sep =「」))+將它們粘貼在一起,並嘗試as.call,但沒有任何好的結果 –

回答

2

建築表達式在R中是相對直接的,其功能類似於as.callbquote以及函數是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