2011-04-16 46 views
2

我想寫一個函數來創建和返回一組參數,以便在我創建的函數mySimulation中使用。到現在爲止,我基本上在做,例如,mySimulation(parm1 = 3, parm2 = 4)。現在這是不理想的,因爲(1)在實際版本中,參數的數量變得很笨重,(2)我想跟蹤生成我正在使用的不同模型的參數的不同組合。所以,我寫了createParms(下面顯示的最低版本)來完成這個技巧。儘管我的整個方法看起來很笨重。所有的統計學家都使用R,我相信有一個更加標準的方法來處理我的問題......對吧?寫一個函數來初始化R/Splus中的參數

createParms <- function(model = "default", ...) { 
    # Returns a list `parms` of parameters which will then be used in 
    # mySimultation(parms) 
    # 
    # Args: 
    # model: ["default" | "mymodel"] character string representation of a model 
    #   with known parameters 
    # ...: parameters of the existing `model` to overwrite. 
    #  if nothing is supplied then the model parameters will be left as is. 
    #  passed variables must be named. 
    #  e.g., `parm1 = 10, parm2 = 20` is good. `10, 20` is bad. 
    # 
    # Returns: 
    # parms: a list of parameters to be used in mySimulation(parms) 
    #   
    parms.names <- c("parm1", "parm2") 
    parms <- vector(mode = "list", length = length(parms.names)) 
    names(parms) <- parms.names 
    overwrite <- list(...) 
    overwrite.names <- names(overwrite) 
    if (model == "default") { 
    parms$parm1 <- 0 
    parms$parm2 <- 0 
    } else if (model == "mymodel") { 
     parms$parm1 <- 1 
     parms$parm2 <- 2 
    } 
    if (length(overwrite) != 0) { 
    parms[overwrite.names] <- overwrite 
    } 
    return(parms) 
} 

回答

1

如果模擬功能始終採用同一組參數,然後將它們存儲在數據幀的Ramnath的做法是最好的。對於mySimulation變量輸入的更一般情況,您應該將每組輸入存儲在列表–中,可能使用一系列列表來運行多個模擬。

createParms函數背後的想法看起來很合理;你可以簡化代碼。

createParms <- function(model = "default", ...) 
{ 
    #default case 
    parms <- list(
    parm1 = 0, 
    parm2 = 0 
) 

    #other special cases 
    if(model == "mymodel") 
    { 
    parms <- within(parms,  
    { 
     parm1 <- 1 
     parm2 <- 2 
    }) 
    } 

    #overwrite from ... 
    dots <- list(...) 
    parms[names(dots)] <- dots 

    parms 
} 

對此進行測試,例如,,

createParms() 
createParms("mymodel") 
createParms("mymodel", parm2 = 3) 

do.call可以派上用場的運行你的模擬,如

do.call(mySimulation, createParms()) 

編輯:do.call爲你做

如果你有parms <- createParms(),然後

do.call(mySimulation, parms) 

相同

with(parms, mySimulation(parm1, parm2)) 

的主要優點是,你不需要拼出要傳遞到mySimulation(或修改函數接受列表形式參數)每個參數。

+0

非常有幫助!已編輯我的功能以反映您的更正。一個後續問題:我從來沒有理解過使用「do.call」。在這種情況下,我想爲什麼不只是'mySimulation(createParms())'。但是在這種情況下'do.call'的優點是我不需要編輯'mySimulation'來處理參數'parms'的列表。它仍然可以按原樣工作......我是否理解這個權利? – lowndrul 2011-04-18 15:32:30

+0

@brianjd:你已經理解正確;看我的編輯。 – 2011-04-18 16:47:35

2

我想,如果你知道這些參數的組合用於每個模型,那麼最好是建立模型的名稱和參數的數據幀如下圖所示

# create a data frame with model names and parameters 
# NOTE: i am assuming all models have equal number of parameters 
# if they are unequal, then store as list of models 

model = c('default', 'mymodel'); 
parm1 = c(0.5, 0.75); 
parm2 = c(1, 2); 

models.df = data.frame(model, parm1, parm2) 

您現在可以通過將它作爲參數傳遞給mySimulation函數來模擬任何模型。我使用了一個虛擬仿真示例,您可以用您的代碼替換它。

# function to run simulation based on model name 

mySimulation = function(model = 'default'){ 

    # find row corresponding to model of interest 
    mod.row = match(model, models.df$model) 

    # extract parameters corresponding to model 
    parms = models.df[mod.row, -1] 

    # run dummy simulation of drawing normal random variables 
    sim.df = rnorm(100, mean = parms[,1], sd = parms[,2]) 
    return(sim.df) 

} 

如果你現在要一步到位運行所有的模擬,你可以使用優秀plyr包並調用

library(plyr) 
sim.all = ldply(models.df$model, mySimulation) 

如果每個模擬返回不等數量的值,那麼你可以使用函數llply而不是ldply

如果您提供了有關模擬返回值的更多信息以及有關其功能的詳細信息,可以輕鬆調整此代碼以獲得所需內容。

讓我知道這是否正常工作

+0

這是一個非常好的解決方案。更快。從我的結尾處獲得更多信息:(1)'mySimulation()'從具有噪聲和動量的跳躍擴散模型返回一條路徑,(2)由於FinMetrics包中的一些好東西,我使用Splus,所以不幸的是, ,我將無法使用'plyr'軟件包 – lowndrul 2011-04-16 22:05:38