如何用 Python 绘制玫瑰图等常见疫情图
程序员文章站
2022-04-15 23:28:04
新冠疫情已经持续好几个月了,目前,我国疫情已经基本控制住了,而欧美国家正处于爆发期,我们会看到很多网站都提供了多种疫情统计图,今天我们使用 Python 的 pyecharts 框架来绘制一些比较常见的统计图。 玫瑰图 首先,我们来绘制前段时间比较火的南丁格尔玫瑰图,数据来源我们通过接口 来获取,我 ......
新冠疫情已经持续好几个月了,目前,我国疫情已经基本控制住了,而欧美国家正处于爆发期,我们会看到很多网站都提供了多种疫情统计图,今天我们使用 python 的 pyecharts 框架来绘制一些比较常见的统计图。
玫瑰图
首先,我们来绘制前段时间比较火的南丁格尔玫瑰图,数据来源我们通过接口 `https://lab.isaaclin.cn/ncov/zh` 来获取,我们取疫情中死亡人数超过 2000 的国家的数据,实现代码如下:
url = 'https://lab.isaaclin.cn/ncov/api/area' data_json = requests.get(url).json() country_list = [] count_list = [] ds = {} for item in data_json['results']: if item['countryenglishname']: if item['deadcount'] is not none and item['countryname'] is not none: if int(item['deadcount']) > 2000: d = {item['countryname']:item['deadcount']} ds.update(d) ds = dict(sorted(ds.items(), key = lambda k: k[1])) # 名称有重复的,把国家名作为 key 吧 country_list = ds.keys() count_list = ds.values() # 随机颜色生成 def randomcolor(kind): colors = [] for i in range(kind): colarr = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'] color = "" for i in range(6): color += colarr[random.randint(0, 14)] colors.append("#" + color) return colors color_series = randomcolor(len(count_list)) # 创建饼图 pie = pie(init_opts=opts.initopts(width='800px', height='900px')) # 添加数据 pie.add("", [list(z) for z in zip(country_list, count_list)], radius=['20%', '100%'], center=['60%', '65%'], rosetype='area') # 设置全局配置 # pie.set_global_opts(title_opts=opts.titleopts(title='南丁格尔玫瑰图'), # legend_opts=opts.legendopts(is_show=false)) # 设置全局配置项 pie.set_global_opts(title_opts=opts.titleopts(title='全球新冠疫情',subtitle='死亡人数超过\n2000 的国家', title_textstyle_opts=opts.textstyleopts(font_size=15,color= '#0085c3'), subtitle_textstyle_opts= opts.textstyleopts(font_size=15,color= '#003399'), pos_right= 'center',pos_left= '53%',pos_top= '62%',pos_bottom='center' ), legend_opts=opts.legendopts(is_show=false)) # 设置系列配置和颜色 pie.set_series_opts(label_opts=opts.labelopts(is_show=true, position='inside', font_size=12, formatter='{b}:{c}', font_style='italic', font_family='microsoft yahei')) pie.set_colors(color_series) pie.render('南丁格尔玫瑰图.html')
看一下效果图:
全球疫情地图
接着我们来绘制全球疫情地图,我们取各个国家的累计死亡人数的数据,代码实现如下所示:
url = 'https://lab.isaaclin.cn/ncov/api/area' data = requests.get(url).json() oversea_confirm = [] for item in data['results']: if item['countryenglishname']: oversea_confirm.append((item['countryenglishname'] .replace('united states of america', 'united states') .replace('united kiongdom', 'united kingdom'), item['deadcount'])) world_map = ( map(init_opts=opts.initopts(theme='dark')) .add('累计死亡人数', oversea_confirm, 'world',is_map_symbol_show=false, is_roam=false) .set_series_opts(label_opts=opts.labelopts(is_show=false, color='#fff')) .set_global_opts( title_opts=opts.titleopts(title='全球疫情累计死亡人数地图'), legend_opts=opts.legendopts(is_show=false), visualmap_opts=opts.visualmapopts(max_=2700, is_piecewise=true, pieces=[ {"max": 99999, "min": 10000, "label": "10000人及以上", "color": "#8a0808"}, {"max": 9999, "min": 1000, "label": "1000-9999人", "color": "#b40404"}, {"max": 999, "min": 500, "label": "500-999人", "color": "#df0101"}, {"max": 499, "min": 100, "label": "100-499人", "color": "#f78181"}, {"max": 99, "min": 10, "label": "10-99人", "color": "#f5a9a9"}, {"max": 9, "min": 0, "label": "1-9人", "color": "#ffffcc"}, ]) ) ) world_map.render(path='全球疫情地图.html')
看一下效果图:
中国疫情地图
我们接着绘制我国的疫情地图,数据取各个省份累计确诊人数的数据,代码实现如下所示:
url = 'https://lab.isaaclin.cn/ncov/api/area' data = requests.get(url).json() province_data = [] for item in data['results']: if item['countryname'] == '中国': province_data.append((item['provinceshortname'], item['confirmedcount'])) china_map = ( map(init_opts=opts.initopts(theme='dark')) .add('确诊人数', province_data, 'china',is_map_symbol_show=false, is_roam=false) .set_series_opts(label_opts=opts.labelopts(is_show=true, color='#ffffff')) .set_global_opts( title_opts=opts.titleopts(title="中国疫情累计确诊人数地图"), legend_opts=opts.legendopts(is_show=false), visualmap_opts=opts.visualmapopts(max_=2000, is_piecewise=true, pieces=[ {"max": 9999, "min": 1000, "label": "1000-9999人", "color": "#b40404"}, {"max": 999, "min": 500, "label": "500-999人", "color": "#df0101"}, {"max": 499, "min": 100, "label": "100-499人", "color": "#f78181"}, {"max": 99, "min": 10, "label": "10-99人", "color": "#f5a9a9"}, {"max": 9, "min": 0, "label": "1-9人", "color": "#ffffcc"}, ]) ) ) china_map.render(path='中国疫情地图.html')
看一下效果图:
热力图
我们再接着来绘制热力图,我们还是取我国各个省份确诊的数据,实现代码如下所示:
url = 'https://lab.isaaclin.cn/ncov/api/area' data = requests.get(url).json() cities_data = [] for item in data['results']: if item['countryname'] == '中国': if item['cities'] is not none: cities_data.extend(item['cities']) hot_geo = ( geo(init_opts=opts.initopts(theme='dark')) .add_schema(maptype='china') .add('累计确诊人数', [(i['cityname'], i['currentconfirmedcount']) for i in cities_data if i['cityname'] in pyecharts.datasets.coordinates.keys()], type_='heatmap') .set_global_opts( title_opts=opts.titleopts(title='中国疫情热力图', pos_left='left'), legend_opts=opts.legendopts(is_show=false), visualmap_opts=opts.visualmapopts(is_show=true, is_piecewise=false, range_color=['#0ff', '#0f0', '#ff0', '#f00']) ) ) hot_geo.render(path='中国疫情热力图.html')
看一下效果图:
柱状图
我们接着来绘制柱状图,这次我们取一个省份的数据,因为湖北省确诊人数最多,我们就用这个省的数据吧,实现代码如下所示:
url = 'https://lab.isaaclin.cn/ncov/api/area' data = requests.get(url).json() for item in data['results']: if item['provinceshortname'] == '湖北': hb_data = item['cities'] hb_bar = ( bar(init_opts=opts.initopts(theme='dark')) .add_xaxis([hd['cityname'] for hd in hb_data]) .add_yaxis('累计确诊人数', [hd['confirmedcount'] for hd in hb_data]) .add_yaxis('累计治愈人数', [hd['curedcount'] for hd in hb_data]) .reversal_axis() .set_series_opts(label_opts=opts.labelopts(is_show=false)) .set_global_opts( title_opts=opts.titleopts(title="湖北新冠疫情确诊及治愈情况"), legend_opts=opts.legendopts(is_show=true) ) ) hb_bar.render(path='湖北新冠疫情图.html')
看一下效果图:
折线图
目前上面的接口已经不提供返回时间序列的数据了,但在 github 上提供了数据仓库,有 json 和 csv 两种格式,因 github 网速太差,我尝试了几次也未能将数据下载下来,所以我们直接用微信上展示的数据吧,代码实现如下所示:
x_data = ['2-06', '2-13', '2-20', '2-27', '3-05', '3-12', '3-19', '3-26', '4-02', '4-09', '4-17'] # 现有确诊 y1_data = [20677, 46537, 49156, 36829, 22695, 13171, 6287, 2896, 987, 351, 122] # 累计治愈 y2_data = [817, 4131, 11788, 26403, 41966, 51533, 58381, 61731, 63612, 64236, 63494] line = (line() .add_xaxis(x_data) .add_yaxis('现有确诊', y1_data, color='#10aeb5') .add_yaxis('累计治愈', y2_data, color='#e83132') .set_series_opts(label_opts=opts.labelopts(is_show=true)) .set_global_opts( title_opts=opts.titleopts(title='中国疫情随时间变化趋势') )) line.render(path='中国疫情折线图.html')
看一下效果图:
如果需要源码,可以扫描下面二维码,后台回复 200418 自行领取。