【问题标题】:How to loop through parameter values, run function, and save results如何循环遍历参数值、运行函数和保存结果
【发布时间】:2020-05-22 20:00:00
【问题描述】:

我将模拟写入一个函数,以便我可以手动设置参数值并使用这些参数值多次运行模拟。为了了解不同的设置如何影响我的模拟结果,我一直在手动更改参数值、运行模拟并保存输出。我反复这样做并将输出数据绑定在一起以进行分析/可视化,但如果我可以自动化这个过程会更方便。

如何循环遍历参数值、运行模拟并将所有结果保存在单个数据框中?


我的代码感觉如下:

#### load libraries ####

library(plyr)
library(igraph)

#### set parameters N and StDv ####

N <- 10 

StDv <- 0.1

#### my model to be simulated, written as a function ####
myModel <- function(){

  #generate small world network, netSim, for the agents
  netSim <- sample_smallworld(dim = 1, nei = 1, size = N, p = 0.1) 

  #retrieve an adjacency matrix from net
  adjMatrix <- as.matrix(as_adjacency_matrix(netSim, names = TRUE, edges = FALSE)) 

  #create dataframe with numbered agents and assigned prior  
  data <- data.frame("agent" = c(1:N),
                     "t0" = rnorm(N, mean = 0.5, sd = StDv))

  #simulate communication and in the network for 5 rounds

  #round 1
  data$t1 <- with(data, ifelse(rowSums(adjMatrix) > 0,  
                               0.75 * t0 + (1-0.75) * (adjMatrix %*% t0 / rowSums(adjMatrix)), 
                               t0)) 

  #round 2
  data$t2 <- with(data, ifelse(rowSums(adjMatrix) > 0,  
                               0.75 * t1 + (1-0.75) * (adjMatrix %*% t1 / rowSums(adjMatrix)), 
                               t1)) 

  #round 3
  data$t3 <- with(data, ifelse(rowSums(adjMatrix) > 0,  
                               0.75 * t2 + (1-0.75) * (adjMatrix %*% t2 / rowSums(adjMatrix)), 
                               t2)) 

  #round 4
  data$t4 <- with(data, ifelse(rowSums(adjMatrix) > 0, 
                               0.75 * t3 + (1-0.75) * (adjMatrix %*% t3 / rowSums(adjMatrix)), 
                               t3)) 

  #round 5
  data$t5 <- with(data, ifelse(rowSums(adjMatrix) > 0,  
                               0.75 * t4 + (1-0.75) * (adjMatrix %*% t4 / rowSums(adjMatrix)), 
                               t4)) 


  #calculate measures of interest
  colResponses <- colMeans(data[2:7])
  colErrorSq <- (colResponses-1)^2
  variance <- as.vector(sapply(data[2:7], function(i)
    var(i)))
  data2 <- data[2:7] 
  data2 <- (data2-1)^2
  avgIndErrSq <- colMeans(data2)
  rm(data2)

  #bind together output 
  Output <- data.frame("N" = N,
                       "StDv" = StDv,
                       "Time" = c("t0", "t1", "t2", "t3", "t4", "t5"),
                       "Collective.Response" = colResponses,
                       "Collective.Error.Squared" = colErrorSq,
                       "Variance" = variance,
                       "Avg.Ind.Error.Squared" = avgIndErrSq)

}

#### Simulate my model by running the function 100 times and saving the results as "myResults" ####
myResults <- ldply(1:100, function(i) data.frame(Iteration = i, myModel())) 

我有我想在向量中探索的所有N 值:N_values &lt;- c(10, 20, 40, 80)

以及我想在向量中探索的所有StDv 值:StDv_values &lt;- c(0.05, 0.1, 0.25, 0.5)

有没有办法遍历NStDv 的每个组合,运行模拟并将结果保存在单个数据帧中?

【问题讨论】:

    标签: r loops automation parameter-passing simulation


    【解决方案1】:

    我建议使用 for 循环来循环浏览您的选项。嵌套的 for 循环应该循环遍历这些向量的所有值和组合。

    #Loop through all N values in vector
    for (i in 1:length(N_values)) {
    
        N = N_values[i]
    
        #Loop through all StDev values in vector for each 
        #iteration of all N values
        for (j in 1:length(StDv_values) {
    
            StDv = StDv_values[j]
    
            MyModel <- insert your model here... etc...
        }
    }
    

    如果可以的话……你有#bind together output 和代码:

    Output <- data.frame("N" = N,
                     "StDv" = StDv,
                     "Time" = c("t0", "t1", "t2", "t3", "t4", "t5"),
                     "Collective.Response" = colResponses,
                     "Collective.Error.Squared" = colErrorSq,
                     "Variance" = variance,
                     "Avg.Ind.Error.Squared" = avgIndErrSq)
    

    您正在创建一个数据框,但我没有看到它绑定到任何东西。

    为了汇总您的所有数据,我建议如下:

    1) 在 for 循环之外初始化一个 NULL 变量 2) 每次迭代将所有新的 Output data.frame 值插入 CompiledDF 变量。

    CompiledDF = NULL
    
    #Loop through all N values in vector
    for (i in 1:length(N_values)) {
    
        N = N_values[i]
    
        #Loop through all StDev values in vector for each 
        #iteration of all N values
        for (j in 1:length(StDv_values) {
    
            StDv = StDv_values[j]
    
            MyModel <- insert your model here... etc...
    
    
            Output <- data.frame(etc...
                                       )
    
            CompiledDF <- rbind(CompiledDF, Output)
    
    
        }
    }
    

    【讨论】:

      【解决方案2】:

      我会编写一个辅助函数来处理使用适当的值组合调用myModel 的重复细节。

      runAll <- function(N_vec, StDv_vec){
        f <- function(N, StDv){
          ldply(1:100, function(i) data.frame(Iteration = i, myModel(N, StDv)))
        }
        vals <- expand.grid(N = N_vec, StDv = StDv_vec)
        res <- Map(function(.N, .StDv){f(.N, .StDv)}, vals$N, vals$StDv)
        res <- do.call(rbind, res)
        row.names(res) <- NULL
        res
      }
      
      N_values <- c(10, 20, 40, 80)
      StDv_values <- c(0.05, 0.1, 0.25, 0.5)
      
      res <- runAll(N_values, StDv_values)
      
      dim(res)
      #[1] 9600    8
      

      但是这仅在函数 myModel 被重新定义为接受两个参数 NStDv 时才有效。函数体保持不变。

      myModel <- function(N, StDv){
        [...]
      }
      

      【讨论】:

        猜你喜欢
        • 2013-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-05
        • 1970-01-01
        • 2020-12-18
        • 1970-01-01
        相关资源
        最近更新 更多