LoginSignup
2
1

More than 1 year has passed since last update.

新型コロナウィルスの第6波を予測して見た

Last updated at Posted at 2022-01-30

はじめに

今回は、新型コロナウィルスの第6波の予測を、SIRモデルを用いながらしたいと思います。

必要なモジュール

プログラムコードは、python

import numpy as np
import matplotlib.pyplot as plt
import matplotlib
%matplotlib inline
import pandas as pd
plt.rcParams['font.family'] = 'Hiragino Sans'
import datetime

データセット

厚生労働省のサイトの「新規陽性者数の推移(日別)」よりダウンロードし、第6波生データ.csvとファイル名を変更した。

df = pd.read_csv('第6波生データ.csv', header=0)
df.head()

Screen Shot 2022-01-28 at 21.45.46.png

表の可視化

大阪府

osaka = df[['Date','Osaka']]
osaka.head()

Screen Shot 2022-01-28 at 21.46.13.png

愛知県

aichi = df[['Date','Aichi']]
aichi.head()

Screen Shot 2022-01-28 at 21.46.31.png

愛知県、京都府、大阪府

aichikyotoosaka = df[['Date','Aichi','Kyoto','Osaka']]
aichikyotoosaka.head()

Screen Shot 2022-01-28 at 21.46.51.png

グラフによる可視化

大阪府

plt.bar(np.arange(osaka['Date'].size), osaka['Osaka'].values)
plt.xlabel("コロナの日数")
plt.ylabel("新規感染者数")
plt.title('大阪府新規感染者数推移')

Screen Shot 2022-01-28 at 21.43.43.png

愛知県

plt.bar(np.arange(aichi['Date'].size), aichi['Aichi'].values)
plt.xlabel('コロナの日数')
plt.ylabel('新規感染者数')
plt.title ('愛知県新規感染者数推移')

Screen Shot 2022-01-28 at 21.47.31.png

第6波の抽出

図より700日後からを第6波とした。

infected=osaka[700:]["Osaka"].values
plt.bar(np.arange(infected.size), infected)

Screen Shot 2022-01-28 at 21.49.04.png

infected=aichi[700:]["Aichi"].values
plt.bar(np.arange(infected.size), infected)

Screen Shot 2022-01-28 at 21.49.30.png

予測モデル

今回は、SIRモデルを用いた。
図はこのサイトより引用。

Screen Shot 2022-01-30 at 10.39.43.png

Screen Shot 2022-01-28 at 21.51.44.png

def SIR_function (sir, t, beta, gamma):
    s,i,r=sir
    ds_dt=-beta*s*i/N
    di_dt=beta*s*i/N-gamma*i
    dr_dt=gamma*i
    return np.array([ds_dt,di_dt,dr_dt])

大阪府の予測

$N$に大阪府の人口、$\beta,\gamma$は適当な値で予測。

N=8850000
beta0,gamma0=0.056,0.045
predict_times=np.arange(200)
times=np.arange(infected.size)

r0=osaka[:700]["Osaka"].values.sum()
i0=infected[0]
sir0=(N-r0+i0,i0,r0)

from scipy.integrate import odeint

predict=odeint(SIR_function,sir0,predict_times,args=(beta0,gamma0))
i=predict[:, 1]

plt.bar(times,infected,label="actual")
plt.plot(predict_times,i,label="predicted", color='orange')
plt.legend()

当然ながらうまく予測できない。

Screen Shot 2022-01-28 at 21.52.41.png

そこで、scipycurve_fitを用いて、$\beta,\gamma$の最適値を求める。

from scipy.optimize import curve_fit

def return_infected (t, beta, gamma):
    predict=odeint(SIR_function,sir0,t,args=(beta,gamma))
    i=predict[:, 1]
    return i

best_params, cov=curve_fit(return_infected, times, infected, (beta0, gamma0), bounds=((0, 0,), (5, 5)))

$\beta=4.99999999,\gamma=4.68203601$が最適値であると算出された。

best_params = array([4.99999999, 4.68203601])

best_beta, best_gamma = best_params
predict=odeint(SIR_function,sir0,predict_times,args=(best_beta,best_gamma))
predict_infected=predict[:, 1] 

plt.bar(times,infected,label="actual")
plt.plot(predict_times,predict_infected,label="predicted", color='orange')
plt.legend()

良い当てはまり具合だと言える。

Screen Shot 2022-01-28 at 21.53.52.png

横軸を日付に変更

startdate = osaka[('Date')][700]

startdate

Screen Shot 2022-01-28 at 21.54.32.png

startdatetime = datetime.datetime.strptime(startdate,'%Y/%m/%d').date()
predict_datetimes = [startdatetime + datetime.timedelta(days=int(day)) for day in predict_times]
predict_datetimes
best_beta, best_gamma = best_params
predict=odeint(SIR_function,sir0,predict_times,args=(best_beta,best_gamma))
predict_infected=predict[:, 1] 

plt.bar(predict_datetimes[:times.size],infected,label="actual")
plt.plot(predict_datetimes,predict_infected,label="predicted", color='orange')
plt.legend()
plt.xticks(rotation=90)

Screen Shot 2022-01-29 at 9.24.45.png

終わりに

筆者が、予測をした際は1月23日であった。その時の、大阪府の新規感染者数は6217人だった。このSIRモデルによると、大阪府の新規感染者数は、2月にピークを迎える。どんどん増え続けている新規感染者数であるが、2月には減少傾向を迎えるだろう。よって、SIRモデルがコロナの新規感染者数を予測するのに、重要なモデルであることを熟知した。これからは、日本国民の3回目のワクチン接種が進めば、第7波は防ぐことができるであろう。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1