考虑以下代码,解决了诸如Lotka-Volterra之类的DE系统。它将解决方案存储在一个名为“out”的列表中,用于4种不同的情况。我有两个问题:
(1)如何计算4个案例的每个时间步的行数并存储到向量中?我尝试使用apply(out[[i]][,1:2],1,sum)
,但它会产生如下错误
FUN中的错误(newX [,i],...):无效的“类型”(列表)
(2)您能解释输出的结构吗?以及为什么它与矩阵一起工作时不起作用。我尝试使用随机数创建类似的列表,但无法重现类似的结构。
感谢。
rm(list=ls())
library("foreach")
library("deSolve")
library(doParallel)
cl<-makeCluster(2, outfile = "debug.txt")
registerDoParallel(cl)
CASES = 4
LVmod <- function(Time, State, Pars) {
with(as.list(c(State, Pars)), {
Ingestion <- rIng * Prey * Predator
GrowthPrey <- rGrow * Prey * (1 - Prey/K)
MortPredator <- rMort * Predator
dPrey <- GrowthPrey - Ingestion
dPredator <- Ingestion * assEff - MortPredator
return(list(c(dPrey, dPredator)))
})
}
solveODE<-function(times, LVmod, pars, yini, CASES){
output<-foreach(x=1:CASES, .packages=c('deSolve')) %dopar%
{
if (x<CASES) ode(yini[[x%%CASES]], times, LVmod, pars)
else ode(yini[[CASES]], times, LVmod, pars)
}
}
pars <- c(rIng = 0.2, # /day, rate of ingestion
rGrow = 1.0, # /day, growth rate of prey
rMort = 0.2 , # /day, mortality rate of predator
assEff = 0.5, # -, assimilation efficiency
K = 10) # mmol/m3, carrying capacity
yini<-list()
yini[[1]]<-c(Prey = 1, Predator = 2)
yini[[2]]<-c(Prey = 5, Predator = 5)
yini[[3]]<-c(Prey = 2, Predator = 3)
yini[[4]]<-c(Prey = 4, Predator = 2)
out<-list()
for (i in 1:CASES) out[[i]]<-list()
for (i in 0:20){
times <- seq(10*i, 10*(i+1), by = 1)
output<-solveODE(times, LVmod, pars, yini, CASES)
for (j in 1:CASES){
out[[j]]<-rbind(out[[j]],output[[j]])
ic11<-out[[j]][length(out[[j]][,1]),2]
ic12<-out[[j]][length(out[[j]][,1]),3]
yini[[j]] <- c(Prey = as.numeric(ic11), Predator = as.numeric(ic12))
}
}
stopCluster(cl)
答案 0 :(得分:2)
使用lapply
代替apply
来循环遍历list
元素;例如,要为每个列表元素计算第二列Prey
中值的总和,您可以执行以下操作:
lapply(out, function(x) sum(as.numeric(x[, 2])))
#[[1]]
#[1] 468.3304
#
#[[2]]
#[1] 461.0533
#
#[[3]]
#[1] 464.6915
#
#[[4]]
#[1] 469.421
至于你的第二个问题:&#34;你能解释一下输出的结构吗?&#34; 好吧,考虑到这是你的代码,这实际上是你应该知道的东西,不是它。根据您的代码,您正在构建list
list
s:
out<-list()
for (i in 1:CASES) out[[i]]<-list()
PS。你真的应该正确格式化你的代码。使用适当的缩进,对齐括号等。这将使您的代码更容易阅读!
如果您想为每个Prey
计算Predator
和time
的总和,可以在rowSums
内使用lapply
:
lst <- lapply(out, function(x) rowSums(as.data.frame(matrix(unlist(x), ncol = 3))[, 2:3]))
as.data.frame(matrix(unlist(x), ncol = 3))
将您的list
转换为data.frame
。
您可以使用list
对cbind
条目进行列绑定:
df <- do.call(cbind, lst));
head(df);
# [,1] [,2] [,3] [,4]
#[1,] 3.000000 10.000000 5.000000 6.000000
#[2,] 3.490136 9.051351 5.445284 7.034600
#[3,] 4.359623 8.130653 5.915932 7.644949
#[4,] 5.467660 7.246250 6.317925 7.842548
#[5,] 6.517990 6.444182 6.589044 7.730863
#[6,] 7.255411 5.759818 6.711389 7.420815
行对应不同的time
值,不同的CASES
列。