Python绘制新冠肺炎疫情图
写在前⾯的话
在《诗经·秦风》中有⼀篇叫做《⽆⾐》的诗歌,其中这样写道:岂⽈⽆⾐?与⼦同袍,与⼦同仇!岂⽈⽆⾐?与⼦同泽,与⼦偕作!岂⽈⽆⾐?与⼦同裳,与⼦偕⾏!这句话的意思就是:谁说没有⾐裳?和你穿同样的战袍,和你同仇敌忾!谁说没有⾐裳?和你穿同样的内⾐,和你共同作准备!谁说没有⾐裳?和你穿同样的战裙,和你共同上前线!
新型冠状病毒感染引发肺炎疫情,各地物资紧急调配驰援武汉,全⼒以赴,坚决打赢疫情防控的阻击战。岂⽈⽆⾐?与⼦同袍、与⼦同泽、与⼦同裳!我们的故事便从这⾥开始说起……
⽬录
⼀、数据分析
⾸先我们需要到新冠肺炎的实时数据,类似于⽀付宝上每天更新的实时数据(由于没有到⽀付宝的实时更新数据,这⾥使⽤腾讯⽹的,也可以使⽤其他⽹站数据)。
下⾯便以⾕歌浏览器为例进⾏说明,使⽤快捷键“F12”之后刷新页⾯,出现如下界⾯。
通过分析发现,以下的两部分为需要的数据。
于是我们得到了需要的url等基本信息,根据获得的信息,我们可以先打印出数据进⾏查看。
import time
import json
import requests
ts = int(time.time()*1000) # 时间戳
data_url = 'view.inews.qq/g2/getOnsInfo?name=disease_h5&callback=&_=%d'%ts
print("url:" + data_url)
data = json.(url=data_url).json()['data']) # requests库获取数据
data = data['areaTree'][0]['children']
print(data)
部分结果如下:
url:view.inews.qq/g2/getOnsInfo?name=disease_h5&callback=&_=1583757380728
[{'name': '湖北', 'today': {'confirm': 36, 'confirmCuts': 0, 'isUpdated': True, 'tip': ''}, 'total': {'confirm': 67743, 'suspect': 0, 'dead': 3007, 'deadRate': '4.44', 'showRate'⼆、获取数据
既然可以通过如此简单的⽅法获取数据,我们接下来就需要获取我们需要的数据。
1、⾸先需要获取每天的数据。
def get_everyday_data(everyday_data_url):
'''
获取每天的数据
:param everyday_data_url: 存放每天数据的路径
:return: 返回每天的数据列表,分确诊、疑似、死亡和治愈
'''
data = json.(url=everyday_data_url).json()['data']) # 获取数据
data.sort(key=lambda x: x['date']) # 将数据按照时间升序排序
# 定义相关数据列表:⽇期列表、确诊列表、疑似列表、死亡列表、治愈列表
date_list, confirm_list, suspect_list, dead_list, heal_list = list(), list(), list(), 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
2、获取各区域确诊分布数据。
def get_area_distribution_data(area_distribution_data_url):
'''
获取各区域确诊分布数据
:
param area_distribution_data_url: 存放区域分布数据的路径
:return: 返回各区域确诊的字典数据
'''
result_data = {} # 存储结果数据的字典
data = json.(url=area_distribution_data_url).json()['data'])['areaTree'][0]['children'] # 获取数据
# 迭代数据,获取需要的数据
for item in data:
if item['name'] not in result_data: # 将区域名称设置为字典的key
result_data.update({item['name']: 0})
for city_data in item['children']: # 将确诊数据作为字典的value
result_data[item['name']] += int(city_data['total']['confirm'])
return result_data
三、绘制疫情图
使⽤matplotlib库进⾏疫情图的绘制,主代码如下:
1、绘制每⽇疫情曲线图
def plot_curve_graph():
'''
绘制每⽇疫情曲线图
:return:
'''
date_list, confirm_list, suspect_list, dead_list, heal_list = get_everyday_data(everyday_data_url) # 获取每天的数据
# 设置标题等相关参数
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, heal_list, label='治愈')
plt.plot(date_list, dead_list, label='死亡')
plt.legend() # 显⽰图例
plt.savefig('2019-nCoV疫情曲线.png') # 保存为⽂件
2、绘制各区域确诊分布图
def plot_distribution_graph(province_positions):
'''
绘制各区域确诊分布图
:param province_positions: 各省位置
:return:
'''
data = get_area_distribution_data(area_distribution_data_url) # 获取各区域确诊分布数据
# 相关参数设置
width, height, rect, lat_min, lat_max, lon_min, lon_max = 1600, 800, [0.1, 0.12, 0.8, 0.8], 0, 60, 77, 140
# 经纬投影替换为如下设置
# width, height, rect, lat_min, lat_max, lon_min, lon_max = 3000, 1500, [0, 0, 1, 1], -90, 90, 0, 360
# width, height, rect, lat_min, lat_max, lon_min, lon_max = 3000, 1500, [0, 0, 1, 1], -90, 90, 0, 360
# 匹配图例颜⾊
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(width / 100, height / 100)
axes = fig.add_axes(rect)
# 局部兰博托投影
# m = Basemap(projection='lcc', llcrnrlon=77, llcrnrlat=14, urcrnrlon=140, urcrnrlat=51, lat_1=33, lat_2=45,
# lon_0=100, ax=axes)
# 全局兰博托投影北京疫情最新数据
# m = Basemap(projection='lcc', llcrnrlon=80, llcrnrlat=0, urcrnrlon=140, urcrnrlat=51, lat_1=33, lat_2=45,
# lon_0=100, ax=axes)
# 局部圆柱投影
# m = Basemap(llcrnrlon=lon_min, urcrnrlon=lon_max, llcrnrlat=lat_min, urcrnrlat=lat_max, resolution='l', ax=axes)
# 正射投影
# m = Basemap(projection='ortho', lat_0=36, lon_0=102, resolution='l', ax=axes)
# 经纬投影
m = Basemap(llcrnrlon=lon_min, urcrnrlon=lon_max, llcrnrlat=lat_min, urcrnrlat=lat_max, resolution='l', ax=axes) m.etopo()
# 读取shape⽂件,shape⽂件主要的作⽤是:画海陆分界线、国界线、⾏政分界线。
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 p_info, p_shape in zip(m.province_info, m.province): # 分析shape⽂件,得到相关省数据
p_name = p_info['OWNER'].strip('\x00')
f_cname = p_info['FCNAME'].strip('\x00')
if p_name != f_cname: # 不绘制海岛
continue
for key in data.keys(): # 设置不同数据范围区域的颜⾊
if key in p_name:
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(p_shape, facecolor=color, edgecolor=color)
axes.add_patch(poly)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论