如何循环遍历参数值,运行 函数,并保存结果
How to loop through parameter values, run function, and save results
我将模拟写入一个函数,这样我就可以手动设置参数值,然后 运行 使用这些参数值进行多次模拟。为了查看不同的设置如何影响我的模拟结果,我一直在手动更改参数值、运行 模拟并保存输出。我反复这样做并将 analysis/visualisation 的输出数据绑定在一起,但如果我可以自动执行此过程会方便得多。
如何遍历参数值,运行 模拟,并将所有结果保存在一个数据帧中?
我的代码感觉如下:
#### 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 <- c(10, 20, 40, 80)
以及我想在向量中探索的所有 StDv
值:StDv_values <- c(0.05, 0.1, 0.25, 0.5)
有没有办法遍历 N
和 StDv
、运行 模拟的每个组合,并将结果保存在单个数据框中?
我建议使用 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) 将所有新的输出 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)
}
}
我会编写一个辅助函数来处理使用适当的值组合调用 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
被重新定义为接受两个参数 N
和 StDv
时有效。函数体保持完全相同。
myModel <- function(N, StDv){
[...]
}
我将模拟写入一个函数,这样我就可以手动设置参数值,然后 运行 使用这些参数值进行多次模拟。为了查看不同的设置如何影响我的模拟结果,我一直在手动更改参数值、运行 模拟并保存输出。我反复这样做并将 analysis/visualisation 的输出数据绑定在一起,但如果我可以自动执行此过程会方便得多。
如何遍历参数值,运行 模拟,并将所有结果保存在一个数据帧中?
我的代码感觉如下:
#### 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 <- c(10, 20, 40, 80)
以及我想在向量中探索的所有 StDv
值:StDv_values <- c(0.05, 0.1, 0.25, 0.5)
有没有办法遍历 N
和 StDv
、运行 模拟的每个组合,并将结果保存在单个数据框中?
我建议使用 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) 将所有新的输出 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)
}
}
我会编写一个辅助函数来处理使用适当的值组合调用 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
被重新定义为接受两个参数 N
和 StDv
时有效。函数体保持完全相同。
myModel <- function(N, StDv){
[...]
}