­

抗擊肺炎:新冠肺炎疫情數據可視化及疫情預測分析

  • 2020 年 2 月 19 日
  • 筆記

寫在前面

疫情當前,共克時艱。

在新型冠狀病毒感染的肺炎疫情牽動社會人心的關鍵時刻,本文將利用數據分析、數據挖掘、機器學習相關方法,圍繞疫情態勢展示、疫情走勢預測進行分析,挖掘複雜異構多源數據之間的關聯關係,以形象生動的方式呈現給大家,為奪取防控疫情的勝利貢獻力量!

這裡將使用傳統時間序列模型Prophet、深度學習模型Seq2seq和傳染病模型SIR進行確診人數預測。

數據描述

數據來源https://www.kaggle.com/sudalairajkumar/novel-corona-virus-2019-dataset

該數據集為2019年新型冠狀病毒全球感染病例數、死亡人數和恢復情況的資訊。請注意,這是一個時間序列數據,因此任何一天的病例數都是累積數。數據從2020年1月22日開始提供,每天都將進行更新。

數據集:

-2019ncovdata.csv

-time_series_2019_ncov_confirmed.csv

-time_series_2019_ncov_deaths.csv

-time_series_2019_ncov_recovered.csv

  • Sno – 序列號
  • Date – 觀察日期和時間(MM/DD/YYYY HH:MM:SS)
  • Province / State – 觀察的省或州(丟失時可以為空)
  • Country – 國家
  • Last Update – 以UTC為單位的時間,在該時間為給定的省或國家更新行。(目前沒有標準化。所以請在使用前清洗)
  • Confirmed – 確診人數
  • Deaths – 死亡人數
  • Recovered – 治癒人數

本文主要使用2019ncovdata.csv數據

數據分析

1.基本導入

import pandas as pd  import numpy as np  import matplotlib.pyplot as plt  import seaborn as sns  import scipy.stats as stats  %matplotlib inline  plt.style.use('ggplot')    import plotly.express as px  import plotly.graph_objs as go  from plotly.offline import iplot, init_notebook_mode  import plotly.figure_factory as ff  from plotly import subplots  from plotly.subplots import make_subplots  init_notebook_mode(connected=True)    from datetime import datetime, date, timedelta    from fbprophet import Prophet    import warnings  warnings.filterwarnings('ignore')    pd.set_option('display.max_columns', 100)  pd.set_option('display.max_rows', 100)

2. 數據導入

import os  for dirname, _, filenames in os.walk('/kaggle/input'):      for filename in filenames:          print(os.path.join(dirname, filename))

輸出:

/kaggle/input/novel-corona-virus-2019-dataset/2019_nCoV_data.csv /kaggle/input/novel-corona-virus-2019-dataset/time_series_2019_ncov_deaths.csv /kaggle/input/novel-corona-virus-2019-dataset/time_series_2019_ncov_confirmed.csv /kaggle/input/novel-corona-virus-2019-dataset/time_series_2019_ncov_recovered.csv

df = pd.read_csv('/kaggle/input/novel-corona-virus-2019-dataset/2019_nCoV_data.csv')  df.head(5)

3.缺失值處理

可以看到省/州這列存在明顯缺失,詳細查看一下原因。

df[df['Province/State'].isnull()]

對於一些國家是沒有省/州相關資訊的,所以為空。

4.已確診情況可視化

首先是全球情況

fig = px.bar(df, x='Date', y='Confirmed', hover_data=['Province/State', 'Deaths', 'Recovered'], color='Country')  annotations = []  annotations.append(dict(xref='paper', yref='paper', x=0.0, y=1.05,                                xanchor='left', yanchor='bottom',                                text='Confirmed bar plot for each country',                                font=dict(family='Arial',                                          size=30,                                          color='rgb(37,37,37)'),                                showarrow=False))  fig.update_layout(annotations=annotations)  fig.show()
這裡是中國的確診情況
fig = px.bar(df.loc[dataset['Country'] == 'Mainland China'], x='Date', y='Confirmed', hover_data=['Province/State', 'Deaths', 'Recovered'], color='Province/State')  annotations = []  annotations.append(dict(xref='paper', yref='paper', x=0.0, y=1.05,                                xanchor='left', yanchor='bottom',                                text='Confirmed bar plot for Mainland China',                                font=dict(family='Arial',                                          size=30,                                          color='rgb(37,37,37)'),                                showarrow=False))  fig.update_layout(annotations=annotations)  fig.show()

中國死亡人數情況

湖北地區死亡人數/治癒人數

數據聚合
confirmed_training_dataset = pd.DataFrame(dataset[dataset.Country=='China'].groupby('Date')['Confirmed'].sum().reset_index()).rename(columns={'Date': 'ds', 'Confirmed': 'y'})  confirmed_training_dataset.head()
日期特徵沒有等距間隔,這是因為數據是在一天中的某個時間存儲的,而不是實時的。此處我們假設為每天真實的確診數據,以便分析和預測

模型預測 – Prophet

Facebook 所提供的 prophet 演算法不僅可以處理時間序列存在一些異常值的情況,也可以處理部分缺失值的情形,還能夠幾乎全自動地預測時間序列未來的走勢。prophet 所做的事情就是:

  1. 輸入已知的時間序列的時間戳和相應的值;
  2. 輸入需要預測的時間序列的長度;
  3. 輸出未來的時間序列走勢。
  4. 輸出結果可以提供必要的統計指標,包括擬合曲線,上界和下界等。
from fbprophet import Prophet  from fbprophet.diagnostics import cross_validation, performance_metrics  from fbprophet.plot import plot_cross_validation_metric, add_changepoints_to_plot, plot_plotly

我們從建立基本的baseline模型開始,包括每日趨勢。( 當然這不一定會有用,因為日期中的時間不是新確認病例登記的真實時間,所以會存在各種干擾因素)。

prophet = Prophet(      yearly_seasonality=False,      weekly_seasonality = False,      daily_seasonality = True,      seasonality_mode = 'additive')  prophet.fit(confirmed_training_dataset)  future = prophet.make_future_dataframe(periods=7)  confirmed_forecast = prophet.predict(future)

對結果進行可視化分析

fig = plot_plotly(prophet, confirmed_forecast)  annotations = []  annotations.append(dict(xref='paper', yref='paper', x=0.0, y=1.05,                                xanchor='left', yanchor='bottom',                                text='確診人數預測',                                font=dict(family='Arial',                                          size=30,                                          color='rgb(37,37,37)'),                                showarrow=False))  fig.update_layout(annotations=annotations)  fig

Prophet中有年、周和日季節性參數,現在我們試著去掉每日的季節性重新預測。

prophet = Prophet(      yearly_seasonality=False,      weekly_seasonality = False,      daily_seasonality = False,      seasonality_mode = 'additive')  prophet.fit(confirmed_training_dataset)  future = prophet.make_future_dataframe(periods=7)  confirmed_forecast_2 = prophet.predict(future)
效果變得非常的差,接下來看看這兩個模型的平均絕對百分比誤差(MAPE)。
def mean_absolute_percentage_error(y_true, y_pred):      y_true, y_pred = np.array(y_true), np.array(y_pred)      return np.mean(np.abs((y_true - y_pred) / y_true)) * 100    max_date = prophet.ds.max()  y_true = prophet.y.values  y_pred_daily = confirmed_forecast.loc[confirmed_forecast['ds'] <= max_date].yhat.values  y_pred_daily_2 = confirmed_forecast_2.loc[confirmed_forecast_2['ds'] <= max_date].yhat.values    print('包含日季節性 MAPE: {}'.format(mean_absolute_percentage_error(y_true,y_pred_daily)))  print('不包含日季節性 MAPE: {}'.format(mean_absolute_percentage_error(y_true,y_pred_daily_2)))

輸出:

包含日季節性 MAPE: 39.37057017194978 不包含日季節性 MAPE: 162.6290389271529

很明顯這些模型的性能很差,我們可以嘗試在兩個模型中添加一些參數,看看是否有什麼變化,希望有所改進。

在 Prophet 中,般可以設置以下四種參數:

  1. Capacity:在增量函數是邏輯回歸函數的時候,需要設置的容量值。
  2. Change Points:可以通過 n_changepoints 和 changepoint_range 來進行等距的變點設置,也可以通過人工設置的方式來指定時間序列的變點。
  3. 季節性和節假日:可以根據實際的業務需求來指定相應的節假日。
  4. 光滑參數:

changepoint_prior_scale 可以用來控制趨勢的靈活度,

seasonality_prior_scale 用來控制季節項的靈活度,

holidays prior scale 用來控制節假日的靈活度。

如果不想設置的話,使用 Prophet 默認的參數即可。

Prophet具體介紹,請參考:https://zhuanlan.zhihu.com/p/52330017

後續文章會對Seq2seq和SIR預測疫情進行詳細介紹

參考鏈接:

https://www.kaggle.com/shubhamai/coronavirus-eda-future-predictions

https://www.kaggle.com/parulpandey/wuhan-coronavirus-a-geographical-analysis