编写一个函数来初始化R / Splus中的参数

时间:2011-04-16 19:18:26

标签: r s-plus

我想编写一个函数,它将创建并返回一组参数,以便在我创建的函数mySimulation中使用。到目前为止,我基本上一直在做,例如,mySimulation(parm1 = 3, parm2 = 4)。这现在不是最理想的,因为(1)在实际版本中,参数的数量变得难以处理,以及(2)我想跟踪产生我正在使用的不同模型的参数的不同组合。所以,我写了createParms(下面显示的最低限度版本)来完成这个技巧。我的整个方法看起来很笨重。所有统计人员使用R,我确信有一种更标准的方式来处理我的问题......对吗?

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)
}

2 个答案:

答案 0 :(得分: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

如果您提供有关模拟返回值的更多信息以及模拟的详细信息,可以轻松调整此代码以获得所需内容。

让我知道这是否有效

答案 1 :(得分: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的每个参数(或修改该函数以接受列表形式的参数)。