ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

如何用 Python 画出新型冠状病毒疫情地图?

2020-11-03 21:51:20  阅读:307  来源: 互联网

标签:冠状病毒 Python 画出 list matplotlib item plt url data


网上一搜,首先搜到的是腾讯的疫情实时追踪,那就用这个数据源吧。
如何用 Python 画出新型冠状病毒疫情地图?

有了网址怎么抓数据呢?这里,我送大家一双火眼金睛,可以从纷乱中找到最靠谱的下载方式。我习惯用Firefox浏览器,下面的讲解就以Firefox为例(其他浏览器基本类似)。
打开菜单,点击“Web开发者”,在递进菜单中选择"网络":
如何用 Python 画出新型冠状病毒疫情地图?

如何用 Python 画出新型冠状病毒疫情地图?
刷新页面,我们很快就能发现,应答类型为JSON格式的这个请求,最有可能包含我们需要的数据了:如何用 Python 画出新型冠状病毒疫情地图?
如何用 Python 画出新型冠状病毒疫情地图?

如何用 Python 画出新型冠状病毒疫情地图?

深入分析,我们就得到了URL地址、请求方法、参数、应答格式等信息。查询参数中,Callback是回调函数名,我们可以尝试置空,而“_”应该是以毫秒为单位的当前时间戳。
有了这些信息,分分钟就可以抓到数据了。我们先在IDLE中以交互方式抓一下看看效果:

import time, json, requests
url = 'https://view.inews.qq.com/g2/getOnsInfo?name=wuwei_ww_area_counts&callback=&_=%d'%int(time.time()*1000)
data = json.loads(requests.get(url=url).json()['data'])
print(len(data))
301
print(data[0])
{'country': '中国', 'area': '湖北', 'city': '武汉', 'confirm': 698, 'suspect': 0, 'dead': 63, 'heal': 42}
print(data[-1])
{'country': '中国', 'area': '山东', 'city': '枣庄', 'confirm': 2, 'suspect': 0, 'dead': 0, 'heal': 0}

只要两行代码,就可以抓到数据了。怎么样,是不是超级简单?

2.以省为单位画疫情图,我们只需要统计同属一个省的所有地市的确诊数据即可。最终的数据抓取代码如下
import time, json, requests

def catch_distribution():
"""抓取行政区域确诊分布数据"""

data = dict()
url = 'https://view.inews.qq.com/g2/getOnsInfo?name=wuwei_ww_area_counts&callback=&_=%d'%int(time.time()*1000)
for item in json.loads(requests.get(url=url).json()['data']):
    if item['area'] not in data:
        data.update({item['area']:0})
    data[item['area']] += int(item['confirm'])
return data

3.数据可视化,我习惯使用Matplotlib模块。Matplotlib有很多扩展工具包(Toolkits),比如,画3D需要mplot3d工具包,画地图的话,则需要Basemap工具包,以及处理地图投影的Pyproj模块。
另外画海陆分界线、国界线、行政分界线等还需要Shape数据。所需模块请自行安装,Shape文件可以从这里下载(https://github.com/dongli/china-shapefiles)。
绘图用到的矢量字库可以从自己的电脑上随便找一个(我用的是simsun.ttf)。我的主程序是2019nCoV.py,Shape文件下载下来之后,是这样保存的:

如何用 Python 画出新型冠状病毒疫情地图?

如何用 Python 画出新型冠状病毒疫情地图?
以下为全部代码,除了疫情地图,还包括了全国每日武汉肺炎确诊数据的下载和可视化。

-- coding: utf-8 --

import time
import json
import requests
from datetime import datetime
import numpy as np
import matplotlib
import matplotlib.figure
from matplotlib.font_manager import FontProperties
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

plt.rcParams['font.sans-serif'] = ['FangSong'] # 设置默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像时'-'显示为方块的问题

def catch_daily():
"""抓取每日确诊和死亡数据"""

url = 'https://view.inews.qq.com/g2/getOnsInfo?name=wuwei_ww_cn_day_counts&callback=&_=%d'%int(time.time()*1000)
data = json.loads(requests.get(url=url).json()['data'])
data.sort(key=lambda x:x['date'])

date_list = list() # 日期
confirm_list = list() # 确诊
suspect_list = list() # 疑似
dead_list = list() # 死亡
heal_list = list() # 治愈
for item in data:
    month, day = item['date'].split('.')
    date_list.append(datetime.strptime('2020-%s-%s'%(month, day), '%Y-%m-%d'))
    confirm_list.append(int(item['confirm']))
    suspect_list.append(int(item['suspect']))
    dead_list.append(int(item['dead']))
    heal_list.append(int(item['heal']))

return date_list, confirm_list, suspect_list, dead_list, heal_list

def catch_distribution():
"""抓取行政区域确诊分布数据"""

data = {'西藏':0}
url = 'https://view.inews.qq.com/g2/getOnsInfo?name=wuwei_ww_area_counts&callback=&_=%d'%int(time.time()*1000)
for item in json.loads(requests.get(url=url).json()['data']):
    if item['area'] not in data:
        data.update({item['area']:0})
    data[item['area']] += int(item['confirm'])

return data

def plot_daily():
"""绘制每日确诊和死亡数据"""

date_list, confirm_list, suspect_list, dead_list, heal_list = catch_daily() # 获取数据

plt.figure('2019-nCoV疫情统计图表', facecolor='#f4f4f4', figsize=(10, 8))
plt.title('2019-nCoV疫情曲线', fontsize=20)

plt.plot(date_list, confirm_list, label='确诊')
plt.plot(date_list, suspect_list, label='疑似')
plt.plot(date_list, dead_list, label='死亡')
plt.plot(date_list, heal_list, label='治愈')

plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m-%d')) # 格式化时间轴标注
plt.gcf().autofmt_xdate() # 优化标注(自动倾斜)
plt.grid(linestyle=':') # 显示网格
plt.legend(loc='best') # 显示图例
plt.savefig('2019-nCoV疫情曲线.png') # 保存为文件
#plt.show()

def plot_distribution():
"""绘制行政区域确诊分布数据"""

data = catch_distribution()

font = FontProperties(fname='res/simsun.ttf', size=14)
lat_min = 0
lat_max = 60
lon_min = 70
lon_max = 140

handles = [
        matplotlib.patches.Patch(color='#ffaa85', alpha=1, linewidth=0),
        matplotlib.patches.Patch(color='#ff7b69', alpha=1, linewidth=0),
        matplotlib.patches.Patch(color='#bf2121', alpha=1, linewidth=0),
        matplotlib.patches.Patch(color='#7f1818', alpha=1, linewidth=0),

]
labels = [ '1-9人', '10-99人', '100-999人', '>1000人']

fig = matplotlib.figure.Figure()
fig.set_size_inches(10, 8) # 设置绘图板尺寸
axes = fig.add_axes((0.1, 0.12, 0.8, 0.8)) # rect = l,b,w,h
m = Basemap(llcrnrlon=lon_min, urcrnrlon=lon_max, llcrnrlat=lat_min, urcrnrlat=lat_max, resolution='l', ax=axes)
m.readshapefile('res/china-shapefiles-master/china', 'province', drawbounds=True)
m.readshapefile('res/china-shapefiles-master/china_nine_dotted_line', 'section', drawbounds=True)
m.drawcoastlines(color='black') # 洲际线
m.drawcountries(color='black')  # 国界线
m.drawparallels(np.arange(lat_min,lat_max,10), labels=[1,0,0,0]) #画经度线
m.drawmeridians(np.arange(lon_min,lon_max,10), labels=[0,0,0,1]) #画纬度线

for info, shape in zip(m.province_info, m.province):
    pname = info['OWNER'].strip('\x00')
    fcname = info['FCNAME'].strip('\x00')
    if pname != fcname: # 不绘制海岛
        continue

    for key in data.keys():
        if key in pname:
            if data[key] == 0:
                color = '#f0f0f0'
            elif data[key] < 10:
                color = '#ffaa85'
            elif data[key] <100:
                color = '#ff7b69'
            elif  data[key] < 1000:
                color = '#bf2121'
            else:
                color = '#7f1818'
            break

    poly = Polygon(shape, facecolor=color, edgecolor=color)
    axes.add_patch(poly)

axes.legend(handles, labels, bbox_to_anchor=(0.5, -0.11), loc='lower center', ncol=4, prop=font)
axes.set_title("2019-nCoV疫情地图", fontproperties=font)
FigureCanvasAgg(fig)
fig.savefig('2019-nCoV疫情地图.png')

if name == 'main':
plot_daily()
plot_distribution()

2019-nCoV疫情曲线:

如何用 Python 画出新型冠状病毒疫情地图?

2019-nCoV疫情地图:
如何用 Python 画出新型冠状病毒疫情地图?

上图为圆柱投影,这也是Basemap默认的投影模式,我们还可以换用其他投影模式,比如兰勃托等角投影,只需要将97行代码改为:

m = Basemap(projection='lcc', width=5000000, height=5000000, lat_0=36, lon_0=102, resolution='l', ax=axes

兰勃托投影效果如下
如何用 Python 画出新型冠状病毒疫情地图?

还可以使用正射投影:

m = Basemap(projection='ortho', lat_0=30, lon_0=105, resolution='l', ax=axes)

正射投影效果如下:
如何用 Python 画出新型冠状病毒疫情地图?

欢迎继续关注!

标签:冠状病毒,Python,画出,list,matplotlib,item,plt,url,data
来源: https://blog.51cto.com/14482848/2546554

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有