前提
Pythonで新型コロナウイルス感染者の予測をおこなっています。
プログラム初学者のためSIRモデルを用いて過去のデータで数式に当てはめています。
実現したいこと
最小二乗法を用いて実際の感染者のデータにフィットするように曲線を描きたいと考えています。
発生している問題・エラーメッセージ
厚生労働省がサイトで出している新規感染者のデータを抽出しPythonでファイルの読み込みをしてプロットまではできていますが、フィットさせようとしてる曲線が全く立ち上がらず一直線になってしまっています。画像がうまくアップロードできないので後付けでそちらの画像をアップロードします。
青いプロットが今回の実際のデータとなっており、下の真っ直ぐに伸びている直線が最小二乗法によって導出した曲線となっています。
エラーメッセージは出ておりません
該当のソースコード
Python
1import numpy as np 2import matplotlib.pyplot as plt 3from scipy.integrate import odeint 4from scipy import optimize 5import csv 6 7# loading csv-file 8f = open("./COVID_1st_wave1.csv", "r", encoding="UTF-8", errors="", newline="" ) 9fcsv = csv.reader(f, delimiter=",", doublequote=True, lineterminator="\r\n", quotechar='"', skipinitialspace=True) 10 11next(f) # skip to the header of the csv-file 12 13cases = [] 14for row in fcsv: 15 cases.append(int(row[1])) 16 17Tokyo = 13999568 # the population of Tokyo in 2020 18normalized_cases = np.array(cases, dtype = float)/Tokyo 19days = len(cases) 20t = np.arange(days) 21# initial values 22I0 = normalized_cases[0]; S0 = 1.0 - I0; R0 = 0.0 23 24# SIR differential equation 25# S = SIR[0], I = SIR[1], R = SIR[2] 26def SIReq(SIR, t, beta, gamma): 27 dSdt = -beta*SIR[0]*SIR[1] 28 dIdt = beta*SIR[0]*SIR[1] - gamma*SIR[1] 29 dRdt = gamma*SIR[1] 30 31 return [dSdt, dIdt, dRdt] 32 33def I(t, beta, gamma): 34 SEIRlist = odeint(SIReq, (S0, I0, R0), t, args = (beta, gamma)) 35 return SEIRlist[:,1] 36 37optparams, cov = optimize.curve_fit(I, t, normalized_cases) 38print('R0=',optparams[0]/optparams[1]) 39fitted = I(t, *optparams) 40 41plt.scatter(t, cases) 42plt.plot(t, fitted*Tokyo) 43plt.xlabel('the number of days from 2020/2/18') 44plt.ylabel('the number of confirmed cases in Tokyo') 45plt.show() 46f.close() # close the csv-file
試したこと
今回は2月18日から5月23日までの範囲で実際のデータにフィットさせようとしましたがうまくいかなかったのですが、1月24日から5月23日までの範囲ではうまくいきました。
また以前も少し似たような質問をしたことがあり、データの範囲の設定の際に必ず新規感染者が1人はいるところから始めないといけないことがわかっています。
よろしくおねがいいたします。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
初学者なので伺いたいのですがこのサイトでは用いているcsvファイルのアップロードも可能だったりするのでしょうか。
> 初学者なので伺いたいのですがこのサイトでは用いているcsvファイルのアップロードも可能だったりするのでしょうか。
残念ながら,それは不可能です.
かわりに,表を描くことはできます.また,コピペで解答者側が再現しやすいよう,コードブロックにCSVを書くのが主流です.いずれにしろ全データを示す必要はないです(今回は必要かもだけど)
情報ありがとうございます。機会がまたあると思うのでその時載せてみようと思います。
> 用いているcsvファイルのアップロード
https://teratail.com/questions/ifoq8glk78r6rm
の「質問へのコメント」に、melianさんがcsvファイルを使わずにコードを実行する方法を書いてて、その後に私が、それを参考にして下記のコード変更をコメントに書いてます
f = open("./COVID-first_wave.csv", "r", encoding="UTF-8", errors="", newline="" )
fcsv = csv.reader(f, delimiter=",", doublequote=True, lineterminator="\r\n", quotechar='"', skipinitialspace=True)
next(f) # skip to the header of the csv-file
↓ 変更
import pandas as pd
url = 'https://covid19.mhlw.go.jp/public/opendata/newly_confirmed_cases_daily.csv'
df = pd.read_csv(url, parse_dates=['Date'])
df_Tokyo = df.loc[df['Date'].between('2020-02-10', '2020-05-20'), ['Date', 'Tokyo']]
fcsv = np.array(df_Tokyo)
この質問で使ってるデータの場合は、コードを上記のように変更して、抽出する期間の日付を適切に設定すれば、csvファイルをアップロードしなくても、コードで使ってるデータ全体を回答者と共有できると思います

回答3件
あなたの回答
tips
プレビュー