Python實現 新型冠狀病毒傳播模型及預測

原文來自 2020/01/25  https://zhuanlan.zhihu.com/p/103988701?utm_source=wechat_session

1.傳染及發病過程

一個健康人感染病毒後進入潛伏期(時間長度爲Q天),潛伏期之後進入發病期(時間長度爲D天),發病期之後該患者有三個可能去向,分別是自愈、接收隔離、死亡。

2.模型假設

  • 潛伏期Q=7天,根據報道潛伏期爲2~14天,取中間值;
  • 發病期D=10天,根據文獻報告,WHO認定SARS發病期爲10天,假設武漢肺炎與此相同;
  • 潛伏期的患者不具有將病毒傳染給他人的能力;
  • 發病期的患者具有將病毒傳染給他人的能力;
  • 患者在發病期之後不再具有將病毒傳染他人的能力;
  • 假設處於發病期的患者平均每天密切接觸1人,致使該人患病的概率爲γ
  • 最初只有一個人類感染者;
  • 病情自然發展,沒有外部干擾。

3.模型公式

P_{N} = P_{N-1} + P_{N-Q} \cdot \gamma + P_{N-Q-D} \cdot \gamma 

N:人類感染該病毒的天數

P_{N}: 第N天感染該病毒並且處於發病期的患者數量

P_{N-Q} \cdot \gamma : Q天前新被感染患者,當日進入發病期的數量

P_{N-Q-D} \cdot \gamma: 當日發病期滿,不再具有傳染能力的患者數量

4.模型初始值

根據假設,最初只有一個人類感染者,所以:

P_{1} = P_{2} = P_{3} ... = P_{7} = 1

5.實際疫情數據

人類感染病毒且發病的初始日期:根據財新網的報道,官方通報首例不明原因肺炎是在12月8日,考慮到確診之前肯定已經嘗試過各種治療方案無效後認定爲不明原因肺炎,所以有理由認爲該名患者在12月8日已經處於發病期末端,根據假設發病期爲10天,所以可以假設該名患者在11月29號發病,即N=1對應11月29日。

日新增發病數 \Delta P_{n}

近期疫情防控大事記:

從以上信息可以判斷核酸檢測試劑是在1月16日、17日大幅使用的,18日、19日確診大量病例,因此1月20日之前的確診病例數對模型參考意義不大。1月20日之後,可以認爲新發病例,發病即檢測。

截至1月20日24時,國家衛健委公告累計確診病例291

截至1月21日24時,國家衛健委公告累計確診病例440

截至1月22日24時,國家衛健委公告累計確診病例571

截至1月23日24時,國家衛健委公告累計確診病例830

截至1月24日24時,國家衛健委公告累計確診病例1287

所以:

  • 1月21日新增確診病例:440-291=149
  • 1月22日新增確診病例:571-440=131
  • 1月23日新增確診病例:830-571=259
  • 1月24日新增確診病例:1287-830=457

考慮到:

  • 1月20日之後發病即檢測
  • 確診檢測用時2日
  • 國外新增病例在個位數,且不能保證發病即檢測等因素,暫不考慮
  • 新增病例應該遞增,所以1月22日新增數據異常,捨去

使用上溯每日新增數據,同時考慮到確診需要2天, 可以得到:

\Delta P_{52} = 149\Delta P_{54} = 259\Delta P_{55} = 457

( P_{1} 對應11月29日 ) 

6.擬合確定 \gamma

根據近期每日新增數據、模型初始值及模型公式,用最小二乘擬合得到 \gamma = 0.55

7.預測

患者數量:根據上文確定的模型及參數,從11月29日(N=1)至1月27日(N=60)人羣中累計處於發病期的人數如下圖所示:

根據模型,近期人羣中患者數量計算如下:

人羣中感染了病毒並處於發病期的患者數量,注意Pn一般需要延期2日才能確診

每日新增患者數量:

根據模型,近期人羣中每日新增患者數量計算如下:

注意:圖中是人羣中新增發病患者數量,可與晚2日的政府發佈新增數量進行對比。即22日新增患者數量可與24日政府發佈的新增病例進行對比。截至目前模型計算22日新增爲369人,政府公佈的24日新增病例457人

根據以上模型預計未來幾日的情況如下:

1月25日將新確診432例,人羣中發病患者爲4068人;

1月26日將新確診505例,人羣中發病患者爲4759人;

1月27日將新確診590例,人羣中發病患者爲5568人;

1月28日將新確診691例,人羣中發病患者爲6514人;

1月29日將新確診809例,人羣中發病患者爲7621人。

由於1月20日之後採取的各種措施,將導致發病期D下降,感染概率 \gamma 下降,1月29日之後日均增長勢頭會減弱。

8.模型代碼

import numpy as np
import matplotlib.pyplot as plt

gamma = 0.55
Q = 7
D = 10
P = np.zeros(300, dtype=np.float)
Psum = np.zeros(300, dtype=np.float)
for i in range(Q):
    P[i] = 1
for j in range(300-Q):
    P[j+Q] = P[j+Q-1]+P[j]*gamma
    if j+Q-D-Q >= 0:
        P[j+Q] -= P[j+Q-D-Q]*gamma
    if j+Q == D:
        P[j+Q] -= 1
plt.xlabel("N")
plt.ylabel("PN")
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.plot(range(1, 61), P[0:60])
plt.grid()
plt.show()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章