2

我想编写一个函数,该函数将创建并返回一组要在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)
}
4

2 回答 2

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.

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

让我知道这个是否奏效

于 2011-04-16T20:19:42.913 回答
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(或修改该函数以接受列表形式的参数)。

于 2011-04-18T11:10:06.697 回答