欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【新冠肺炎】SIR模型预测与数据分析之代码篇

程序员文章站 2022-04-27 12:25:10
...

【新冠肺炎】SIR模型预测之代码篇

关键词:新冠肺炎,SIR模型预测,数据分析
本篇使用R语言

之前我们介绍过了SIR模型的基本理论以及其微分方程,不熟悉的朋友可以看这篇:
SIR SIRE 传染病预测模型与代码应用之概念篇
根据SIR模型的微分方程我们了解到病毒传染的各种特征,比如何时结束,最大规模,疫情的控制手段,以及疫苗和群体免疫问题,不熟悉的朋友可以回顾一下这一篇:
【cov-19】新冠肺炎的SIR模型补充与应用

在掌握这些基础知识后,我们可以根据微分方程在R中搭建一个SIR模型,并通过模型预测病毒的整体走向。其实我们知道,对于预测问题来说,建立模型是非常简单的,提升准确度的关键主要是调参,以及概念上的修改。这里我们简单介绍一下如何搭建模型以及对比预测。
首先强调,模型预测并不可靠,只能表现出一些数据上的趋势,真实情况还是需要根据事实自我判断。

1.建立模型
思路:先编辑好SIR模型,后用ode完成模拟:
注:这里使用的是fraction的方程,也就是百分比数量。

sir_model <- function(beta, gamma, S0, I0, R0, times) {
  require(deSolve)
  #----------SIR微分模型
  sir_equations <- function(time, variables, parameters) {
    with(as.list(c(variables, parameters)), {#使用百分比的fraction方程
      dS <- -beta * I * S
      dI <-  beta * I * S - gamma * I
      dR <-  gamma * I
      return(list(c(dS, dI, dR)))
    })
  }
  #----------定义变量
  parameters_values <- c(beta  = beta, gamma = gamma)
  initial_values <- c(S = S0, I = I0, R = R0)
  
  #---------通过ode模拟疫情
  out <- ode(initial_values, times, sir_equations, parameters_values)
  
  #----------返回结果
  as.data.frame(out)
}     

2.清洗数据以及数据探索
我们开始编写测试主体,这里以加拿大的新冠肺炎数据为例。
2.1数据概览
读入数据:

setwd("~ /SIR_Model/")
source("model_fit.R")#<---SIR模型的主体
cov_df<-read.csv("covid19_5_5.csv")

首先我们概览一下数据长什么样
【新冠肺炎】SIR模型预测与数据分析之代码篇
最左边的pruid是每个省的编号,其中1代表加拿大整体。剩下的variable为
numconf:确诊数
numprob:疑似数
numdeath:死亡数
numtotal:确诊数+疑似数
numtested:测试数
这里我们感兴趣的是加拿大单位时间的总确诊数,也就是numtotal。
2.2数据清洗
打开数据可以发现前期加拿大*并不是很重视疫情的统计,四月之前有一些日期是不连续,那么我们写一个方程来填补时间以及根据对应省id提取出该省的数据:

#date
#date
data_washing<-function(input_dt,prov_id){
  require(lubridate)
  proc_data<-cov_df[cov_df$pruid==prov_id,]
  #formation
  proc_data$date_new<-format(as.Date(proc_data$date,format='%Y-%m-%d'),format='%m-%d')
  proc_data$date<-as.Date(proc_data$date,format='%Y-%m-%d')
  #complete date
  date_start<-ymd(proc_data$date[1])
  date_end<-ymd(proc_data$date[length(proc_data$date)])
  complete_date<-date_start+days(0:as.numeric(date_end-date_start))
  #merge
  df1<-data.frame(date=proc_data$date,numtotal=proc_data$numtotal)
  df2<-data.frame(date=complete_date,c=c(1:length(complete_date)))
  merged_proc_data<-merge(df1,df2,by="date",all=TRUE)
  return(merged_proc_data)
}

2.3透视数据

#data exploring
#<------canada total confirmed
canada_total<-data_washing(cov_df,"1")
trt_total<-data_washing(cov_df,"35")
qbc_total<-data_washing(cov_df,"24")

ggplot(data=canada_total,aes(x=canada_total$date,y=canada_total$numtotal))+
  geom_point(aes(x=canada_total$date,y=canada_total$numtotal,colour="CA_Total"))+
  geom_point(data=trt_total,aes(x=trt_total$date,y=trt_total$numtotal,colour="trt_total"))+
  geom_point(data=qbc_total,aes(x=qbc_total$date,y=qbc_total$numtotal,colour="qbc_total"))+
  theme(axis.text.x = element_text(angle=90,hjust=1))

【新冠肺炎】SIR模型预测与数据分析之代码篇

2.3.1加拿大总体的确诊走向已经进入疫情爆发的前期阶段。
2.3.2 Ontario(安省)*一直对疫情比较重视,比较早的颁布了社交距离禁令,所以总体确诊要低于魁北克。
2.3.3 Quebec(魁北克)*并不是很重视疫情监控,可以看到头铁的魁北克3月之前都没有记录数据,而在开始记录之后的短短15天直接指数起飞。

3.SIR模型数据预测
3.1 先看一下安省,人口为1457万,由于安省的社交禁令比较早,所以S(可能感染者)之间的接触系数也就会比较小。各媒体官方给出的R0为1.4-6.49之间,结合官方数据再加上一顿乱敲,我们取R0=1.9, gamma=0.13,beta=0.24

t<-merged_plot(input_data=trt_total,
               model_duration=seq(1,200),#时间周期200天
               population = 14570000,#安省人口一千四百多万
               beta = 0.25,
               gamma = 0.11)

【新冠肺炎】SIR模型预测与数据分析之代码篇

来一张局部放大图,我们设置时间周期为100天:
【新冠肺炎】SIR模型预测与数据分析之代码篇
根据实际数据显示,截至5月5日,只有0.125%的安省人被感染,也就是18213人左右。而根据模型来看,已感染的人数在1.125%左右,也就是16万多,整整高出10倍。这里有3种可能:1)参数有误差;2)检测样本小,无法体现总确诊;3)人们通过各种手段延缓、抑制了疫情的发展。
可以通过一下方案解决
1)调参:修改beta为平均值0.328,这时的R0为3,可以看到疫情基本上要过去了:
【新冠肺炎】SIR模型预测与数据分析之代码篇
给大家推荐一个网站,可以在线对SIR模型进行模拟,有兴趣的朋友可以试试不同的参数对疫情的情况有什么影响,这里就不多介绍了:
Hans Nesse - Global Health - SIR Model

2)样本容量,“真实”数据也不一定真实。加拿大对于有症状人群的检测方式:
【新冠肺炎】SIR模型预测与数据分析之代码篇
所以这里我们只说模型的应用,不讨论数据。

3.2 预测魁北克省情况
魁省的数据3月以后才出现,而短短15天飙升到几万人,可见这里的beta是偏高的,所以我们取平均值偏低一点儿0.3。这里魁省的人口为260万人。

#qbc
merged_plot(input_data=qbc_total,
               model_duration=seq(1,200),
               population = 2600000,
               beta = 0.3,
               gamma = 0.11)

【新冠肺炎】SIR模型预测与数据分析之代码篇
强调一点,模型的结果并不是一定可靠的,虽然前期很fit,但在实际的情况中,有很多人为的因素是模型无法应变的,比如人们恐慌后开始加强防护措施,保持社交距离等,都会使曲线变得更加平缓,甚至在大爆发前抑制住病毒

第二,对于得到的数据我们所做的模型不应该很完美的fit,毕竟每天检测的sample size有限。打个比方,A市每天检测100名报名的人,而每天确诊的患者都会增加5人。那我们能说A市每天确诊增加了5人吗?真实数字当然远远大于5人,所以我们的模型结果所表示的更应该是一种整体的趋势,而不是用来与特定的样本来比较。且在数据中,我们更应该关心样本中确诊人数的占比。

Ontario比例:
【新冠肺炎】SIR模型预测与数据分析之代码篇
Quebec 比例:
【新冠肺炎】SIR模型预测与数据分析之代码篇
从确诊比例图中我们可以看出,Ontario似乎已经经过了一波高峰,目前已经趋于一个下降的过程。而Quebec还在持续的攀升中。


再次强调,模型预测并不可靠,只能表现出一些数据上的趋势,真实情况还是需要根据事实自我判断。

SIR模型到这里就结束了,需要完整代码可以评论。

Reference:
1. L.Eggertson cmaj News ‘COVID-19: Recent updates on the coronavirus pandemic’
url: https://cmajnews.com/2020/05/06/coronavirus-1095847/
2. Population of Cities in Canada (2020)
url: https://worldpopulationreview.com/countries/canada-population/cities/
3. some r code example
url: https://rpubs.com/choisy/sir