→ obarisk:感覺像chaos 04/20 13:47
→ lin15:R好像有做SIR model的package 04/20 13:51
推 clickhere:你的input和output放錯了, 所以解得不是你給的ode. 04/21 11:28
→ clickhere:雖然ode()可以給變數名,但不代表fortran就懂名字. 04/21 11:29
→ clickhere:fortran只管變數的順序的.你input yini 是 I, S, R. 04/21 11:29
→ clickhere:但在ode()裡卻回傳 c(dI, dS, dR). 04/21 11:30
→ clickhere:改 yini <- c(S = ..., I= ..., R = ...) 即可. 04/21 11:32
→ clickhere: 回傳 c(dS, dI, dR). 04/21 11:33
感謝各位回答!
剛開始先改yini的順序,但還是執行不出預期結果。
後來參考其他人用R語言實作SIR model的程式,
http://archives.aidanfindlater.com/blog/2010/04/20/the-basic-sir-model-in-r/
發現似乎直接把S,I,R定義成proportion就好...
(也就是要把S,I定成999/1000,1/1000)
(如我上述的S,I,R定義,這三個變數其實是proportion)
我一開始是把S,I,R定義成人數,再讓它除以pop_size(族群總人口數),
dS <- -beta*kappa*(S/pop_size)*(I/pop_size)
dI <- beta*kappa*(S/pop_size)*(I/pop_size)-((I/pop_size)/D)
dR <- (I/pop_size)/D
這樣是不符合SIR model公式的。
以下ODE解出來的SIR都是proportion,
但是最後會把out矩陣中的SIR值再乘上pop_size,
以求出人數。
http://pastie.org/7682055
library(deSolve)
pop_size=1000
pars <- c(beta=0.15, kappa=12, D=1)
yini <- c(S=0.999, I=0.001, R=0)
times <- seq(0, 25, by=1)
infection <- function(Time, State, Pars) {
with(as.list(c(State, Pars)), {
dS <- -beta*kappa*S*I
dI <- beta*kappa*S*I-(I/D)
dR <- I/D
return(list(c(dS, dI, dR)))
})
}
out<- ode(func=infection,y=yini,parms=pars,times=times)
out[,2:4] <- pop_size*out[,2:4]
matplot(out[,"time"], out[,2:4], type = "l", xlab = "week", ylab = "numbers",
main = "Infection", lwd = 2)
legend("topright", c("Susceptibles", "Infecteds", "Recovereds"), col = 1:3,
lty = 1:2)
不過,現在還有個問題是...
怎麼作出dS/dt, dI/dt, dR/dt對時間作圖的結果呢?
因為在這個課本的範例中,
大約在第二十週之後感染者人數幾乎是零人,
而且從SIR的圖也可看出,感染者增加的速率是先上升後下降的。(由切線斜率判斷)
也就是說...我似乎需要先寫出d^2X/dt^2 (X=S,I,R)的function才行?
這下變成純粹的數學問題了= ="
I''= βκ(S'I+SI') –I'/D
這樣寫對嗎?
有辦法用R解這種型態的ODE嗎?
→ clickhere:有沒有除pop_size只影響解的範圍.基本上,是順序解錯了. 04/22 00:37
呃...會有影響。
因為這公式對S,I,R的定義就是proportion,
所以要寫成d(S/pop_size)/dt才算得出來?
→ clickhere:你都已有out[,c(2,3,4)]了.何需在解ODE? 04/22 00:38
→ clickhere:out[-1,2] - out[-nrow(out),2] 不是 dS/dt 嗎? 04/22 00:39
感謝指教...
可是out[-1,2] - out[-nrow(out),2]無法把times這個column留下來?
out<- ode(func=infection,y=yini,parms=pars,times=times)
out[,2:4] <- pop_size*out[,2:4]
dout<- out[-1,1:4] - out[-nrow(out),1:4]
week <- times[2:26]
dim(week) <-c(25,1)
#因為times都變成1,只好設定一個叫做week的矩陣代表時間
matplot(week, dout[,2:4], type = "l", xlab = "week", ylab = "numbers", main =
"Infection", lwd = 2)
legend("topright", c("dS/dt", "dI/dt", "dR/dt"), col = 1:3, lty = 1:2)
推 clickhere:proportion!! scale initial kappa & D即可. 04/22 18:47
感謝回答!
※ 編輯: anovachen 來自: 111.255.244.92 (04/23 23:15)