Написание функции для инициализации параметров в R / Splus - PullRequest
2 голосов
/ 16 апреля 2011

Я хотел бы написать функцию, которая будет создавать и возвращать набор параметров для использования в функции 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 ]

2 голосов
/ 17 апреля 2011

Я думаю, что если вы знаете комбинацию параметров, которые будут использоваться для каждой модели, то лучше создать фрейм данных с именами и параметрами модели, как показано ниже

# 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 голос
/ 18 апреля 2011

Если функция моделирования всегда принимает один и тот же набор аргументов, то подход Рамната к хранению их в кадре данных является наилучшим. Для более общего случая переменных входных данных, равных mySimulation, вы должны хранить каждый набор входных данных в списке & ndash; вероятно, используя список списков для запуска нескольких симуляций.

Идея, стоящая за вашей 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 (или изменять эту функцию, чтобы принимать параметры в форме списка).

...