1. 程式人生 > >武漢新型冠狀病毒 - 資料採集、模型預測

武漢新型冠狀病毒 - 資料採集、模型預測

關於武漢新型冠狀病毒的資料採集、模型預測

武漢加油、湖北加油、中國加油!!!

專案背景

2020年開年爆發的武漢新型冠狀病毒,新的一年相信對於大家來說都是地獄模式開局,對於我本人也是如此,打亂了很多計劃,有些不知所措,但是災難面前,唯有同舟共濟,對此我個人是樂觀的,中華民族是不服輸的民族,上下5000年曆史,比這大的災難比比皆是,但是我們依然屹立於此,依然活躍於世界舞臺,這充分證明了中華民族的韌性,中國萬歲;

之前看到丁香園上有實時的動態資料,就想著拉下來進行分析挖掘預測,第一版之前跑了兩天後停止了,因為當時資料格式變化比較大,從2月5號開始第二版資料採集指令碼,指令碼很簡單,目前採集間隔是10分鐘,不是每10分鐘都會採集,這取決於資料是否有變動,這裡主要展示資料採集指令碼以及一個簡單的基於prophet的確診、疑似、死亡、治癒的預測;

資料採集

資料基於丁香園的實時動態資料,感謝資料展示分享,對於大家瞭解疫情的實時情況真的幫助很大,各種資料視覺化展示,大家也可以點進去看看,做的還是比較精細的,顆粒度最低可以到某個市的某個區,這也證明中國目前在全國統籌方面的能力在日益完善,當然還有很長的路要走,畢竟咱們的目標是星辰大海;

採集方式:主要資料分兩部分,一部分是全國的整體情況,一部分是各省市情況,這兩部分都處於script元素內,因此其實只需要找到對應的script元素,對於內容文字做擷取後,轉為json物件即可直接讀取內部內容,而整體結構也是簡潔明瞭,相信大家都能搞定的,下面是我的採集指令碼,可以直接copy執行的,大家需要注意的主要以下幾個點:1. 首先同級目錄建立data_new資料夾,2. 一些註釋要開啟,主要是兩部分註釋是給csv檔案寫頭行的,所以我寫過一次就註釋了,第一次執行需要開啟,後續註釋掉就行,我主要獲取五類資料:城市名、確診數、疑似數(這個只在全國部分有,各省市是沒有的)、死亡數、治癒數;

#!/usr/bin/env python
# coding=utf-8


import requests
from bs4 import BeautifulSoup as BS
import json
import time
import sys,os
reload(sys)
sys.setdefaultencoding('utf-8')


while(True):
    try:
        r = requests.get('https://3g.dxy.cn/newh5/view/pneumonia_peopleapp?from=timeline&isappinstalled=0')
        soup = BS(r.content, 'html.parser')
        _cn_data = soup.find('script',id='getStatisticsService').get_text()
        _s = _cn_data.index('{', _cn_data.index('{')+1)
        _e = _cn_data.index('catch')-1
        _china = json.loads(_cn_data[_s:_e])
        _timestamp = _china['modifyTime']
        _cc,_sc,_dc,_cuc = _china['confirmedCount'],_china['suspectedCount'],_china['deadCount'],_china['curedCount']
        print _timestamp,_cc,_sc,_dc,_cuc
        if open('data_new/湖北省.csv').readlines()[-1].split(',')[0]==str(_timestamp):
        #if False:
            print('data not flush')
        else:
            #row = 'timestamp,confirmedCount,suspectedCount,curedCount,deadCount'
            #os.system('echo '+row+' >> data_new/中國.csv')
            row = ','.join([str(_timestamp),str(_cc),str(_sc),str(_cuc),str(_dc)])
            os.system('echo '+row+' >> data_new/中國.csv')
            _data = soup.find('script',id='getAreaStat').get_text()
            _data =  _data[_data.find('['):_data.rfind(']')+1]
            _provinces = json.loads(_data)
            for _province in _provinces:
                print _timestamp,_province['provinceName'],_province['provinceShortName'],_province['confirmedCount'],_province['suspectedCount'],_province['curedCount'],_province['deadCount'],len(_province['cities'])
                _fn = _province['provinceName']+'.csv'
                #row = 'timestamp,provinceName,cityName,confirmedCount,suspectedCount,curedCount,deadCount,locationId'
                #os.system('echo '+row+' >> data_new/'+_fn)
                for _city in _province['cities']:
                    row = ','.join([str(_timestamp),_province['provinceName'],_city['cityName'],str(_city['confirmedCount']),str(_city['suspectedCount']),str(_city['curedCount']),str(_city['deadCount']),str(_city['locationId'])])
                    os.system('echo '+row+' >> data_new/'+_fn)
    except Exception as e:
        print(e)
        pass
    time.sleep(60*10) # 10分鐘flush一次

再次感謝丁香園的同學們,對於資料沒有做太多保護處理,當然希望大家能夠妥善使用;

疫情資料分析

這部分的程式碼在這裡,大家可以隨便取之食用,用的資料是WHO釋出的全球資料,顆粒度是天,單位是省,分析主要是兩部分第一部分是中國各省情況,第二部分是中國整體情況;

中國各省情況 - 確診人數、死亡/確診、治癒/確診

可以看到,死亡率最高的依然是湖北,不得不說,這次國家採取的措施對於全國、世界是好事,但是對於整個湖北、武漢人民卻承受了太多太多,我想大家都欠他們一聲“你們辛苦了”;

中國整體趨勢 - 確診、死亡、治癒的趨勢圖,死亡率、治癒率、死亡/治癒

可以看到,確診、死亡、治癒人數曲線圖依然沒有緩和的趨勢,但是好訊息是治癒率在上升,而死亡率在下降,這一點從死亡/治癒的先升後降中也能看到;

確診、疑似、死亡、治癒預測

這裡我只用到了全國的總資料做預測,實際上因為指令碼獲取的也有各城市的情況,大家一樣可以對資料來源做一點點修改,就可以做大家感興趣(比如家鄉、工作地、女朋友所在地)等做預測了,還有一個問題需要大家注意,瀏覽資料時會看到資料有一個跳變的過程,這是因為丁香園的資料來源於國家相關部分,而這些資料的釋出應該是有固定時間點的,所以會出現兩個相鄰資料之間,突然增長了一大段的情況,正常,不需要太驚訝;

全國確診人數實際情況(2020/02/05到2020/02/09)+預測(實際資料後24小時)

橫座標是時間,縱座標是人數,右側沒有點的部分的線就是往後24小時的預測人數,可以看到明顯的階梯狀,這個我看了資料後大概是這麼理解的,只有治癒人數是一天內多次有效更新的,其他確診、疑似、死亡基本一天內的資料變動不大,所以看起來會有階梯狀;

疑似

死亡

治癒

把治癒的情況放到了最後,是想強調一下,大家對這次疫情要有足夠的信心,看目前的資料上升趨勢,情況正在逐步得到控制,當然也不可以掉以輕心,隔離依然是最最重要且有效的手段,每個人都做好自己的工作,我相信疫情結束的那一天很快就會到來;

預測部分的程式碼

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from fbprophet import Prophet

df_train = pd.read_csv('./中國.csv', parse_dates=['timestamp'])
df_train['timestamp'] = df_train['timestamp'].apply(lambda ts:pd.Timestamp(int(ts), unit='ms'))
#df_train.sort_values(['timestamp'],inplace=True)

# confirmedCount
df_train_confirmed = df_train[['timestamp','confirmedCount']].copy()
df_train_confirmed = df_train_confirmed.rename(index=str, columns={"timestamp": "ds", "confirmedCount": "y"})
# suspectedCount
df_train_suspected = df_train[['timestamp','suspectedCount']].copy()
df_train_suspected = df_train_suspected.rename(index=str, columns={"timestamp": "ds", "suspectedCount": "y"})
# deadCount
df_train_dead = df_train[['timestamp','deadCount']].copy()
df_train_dead = df_train_dead.rename(index=str, columns={"timestamp": "ds", "deadCount": "y"})
# curedCount
df_train_cured = df_train[['timestamp','curedCount']].copy()
df_train_cured = df_train_cured.rename(index=str, columns={"timestamp": "ds", "curedCount": "y"})

# test
df_test = pd.DataFrame({})
df_test['ds'] = pd.date_range(start=df_train_confirmed.ds.max(), freq="H", periods=24)

m = Prophet()
#m.fit(df_train_confirmed)
#m.fit(df_train_suspected)
#m.fit(df_train_dead)
m.fit(df_train_cured)

forecast = m.predict(pd.concat([df_train_confirmed[['ds']],df_test[['ds']]]))

#print forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()
m.plot(forecast)
plt.xlabel('Date')
plt.ylabel('Cured Count')
plt.show()

最後

引用一句WHO的話:

We must remember that these are people, not numbers.
翻譯過來意思是:我們必須記住這不是數字,而是人。

希望疫情結束後,每個人都能見到自己的親人、朋友、同事、每一個自己關心的人,能夠給他們一個擁抱,謝謝他們還能陪伴自己,謝謝他們沒有拋下自己。

最後的最後

大家可以到我的Github上看看有沒有其他需要的東西,目前主要是自己做的機器學習專案、Python各種指令碼工具、資料分析挖掘專案以及Follow的大佬、Fork的專案等:
https://github.com/NemoHoHaloAi