新冠病毒 - 数据采集、模型预测

2020-10-26 17:51:35 浏览数 (1)

武汉加油、湖北加油、中国加油!!!

相关数据采集、预测仓库地址

项目背景

2020年开年爆发的新型冠状病毒,新的一年相信对于大家来说都是地狱模式开局,对于我本人也是如此,打乱了很多计划,有些不知所措,但是灾难面前,唯有同舟共济,对此我个人是乐观的,中华民族是不服输的民族,上下5000年历史,比这大的灾难比比皆是,但是我们依然屹立于此,依然活跃于世界舞台,这充分证明了中华民族的韧性,中国万岁;

之前看到丁香园上有实时的动态数据,就想着拉下来进行分析挖掘预测,第一版之前跑了两天后停止了,因为当时数据格式变化比较大,从2月5号开始第二版数据采集脚本,脚本很简单,目前采集间隔是10分钟,不是每10分钟都会采集,这取决于数据是否有变动,这里主要展示数据采集脚本以及一个简单的基于prophet的确诊、疑似、死亡、治愈的预测;

数据采集

数据基于丁香园的实时动态数据,感谢数据展示分享,对于大家了解疫情的实时情况真的帮助很大,各种数据可视化展示,大家也可以点进去看看,做的还是比较精细的,颗粒度最低可以到某个市的某个区,这也证明中国目前在全国统筹方面的能力在日益完善,当然还有很长的路要走,毕竟咱们的目标是星辰大海;

采集方式:主要数据分两部分,一部分是全国的整体情况,一部分是各省市情况,这两部分都处于script元素内,因此其实只需要找到对应的script元素,对于内容文本做截取后,转为json对象即可直接读取内部内容,而整体结构也是简洁明了,相信大家都能搞定的,下面是我的采集脚本,可以直接copy运行的,大家需要注意的主要以下几个点:1. 首先同级目录创建data_new文件夹,2. 一些注释要打开,主要是两部分注释是给csv文件写头行的,所以我写过一次就注释了,第一次运行需要打开,后续注释掉就行,我主要获取五类数据:城市名、确诊数、疑似数(这个只在全国部分有,各省市是没有的)、死亡数、治愈数;

代码语言:txt复制
#!/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小时的预测人数,可以看到明显的阶梯状,这个我看了数据后大概是这么理解的,只有治愈人数是一天内多次有效更新的,其他确诊、疑似、死亡基本一天内的数据变动不大,所以看起来会有阶梯状;

疑似

死亡

治愈

把治愈的情况放到了最后,是想强调一下,大家对这次疫情要有足够的信心,看目前的数据上升趋势,情况正在逐步得到控制,当然也不可以掉以轻心,隔离依然是最最重要且有效的手段,每个人都做好自己的工作,我相信疫情结束的那一天很快就会到来;

预测部分的代码

代码语言:txt复制
#!/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

0 人点赞