如何用Python绘制深小卫推文中的病例图

如何用Python绘制深小卫推文中的病例图

前面的文章介绍了如何用Python绘制南丁格尔玫瑰图,链接:循序渐进,学会用pyecharts绘制玫瑰图

南丁格尔玫瑰图最初被用于统计军医数据,现在也常用于疫情数据统计。例如在深圳,大家基本每天都会看卫健委的数据,里面就有玫瑰图。

本文介绍如何使用Python实现相同的玫瑰图。

数据录入

根据原始图形中的数据,先将数据录入到代码中。

# coding=utf-8
import pandas as pd
from pyecharts.charts import Pie
from pyecharts import options as opts

# 根据原始图形录入数据
data = {
    '中国香港': [1234, 2], '美国': [66, 0], '日本': [58, 0], '新加坡': [52, 1], '俄罗斯': [49, 0],
    '加拿大': [43, 1], '韩国': [38, 0], '南非': [23, 0], '泰国': [16, 0], '柬埔寨': [15, 0],
    '印尼': [11, 0], '英国': [9, 0], '阿联酋': [8, 0], '菲律宾': [7, 0], '几内亚': [4, 0],
    '马来西亚': [3, 0], '印度': [3, 0], '尼日利亚': [3, 0], '伊拉克': [2, 0], '毛里求斯': [2, 0],
    '阿尔及利亚': [2, 0], '刚果(金)': [2, 0], '德国': [2, 0], '中国台湾': [2, 0], '土耳其': [1, 0],
    '瑞士': [1, 0], '斯里兰卡': [1, 0], '巴西': [1, 0], '奥地利': [1, 0], '约旦': [1, 0],
    '秘鲁': [1, 0], '塞拉利昂': [1, 0], '加纳': [1, 0], '墨西哥': [1, 0], '澳大利亚': [1, 0],
    '匈牙利': [1, 0], '新西兰': [1, 0], '加蓬': [1, 0], '伊朗': [1, 0], '蒙古': [1, 0],
    '卡塔尔': [1, 0], '肯尼亚': [1, 0], '沙特阿拉伯': [1, 0], '越南': [1, 0]
}

原始数据用字典的方式录入,key表示国家,值使用列表,第一个值表示现有数量,第二个值表示新增数量。

绘制南丁格尔图

# 根据不重复的数据,生成图形的高度值
current_no_repeat = sorted(list(set([num[0] for num in data.values()])))
height_graph = [v for v in range(50, 50+len(current_no_repeat))]
area_dict = {k: v for k, v in zip(current_no_repeat, height_graph)}
overseas = {
    'country': [c for c in data.keys()],
    'current': [num[0] for num in data.values()],
    'new': [num[1] for num in data.values()],
    'area': [area_dict[k] for k in [num[0] for num in data.values()]]
}
df_overseas = pd.DataFrame(overseas)
# 绘制南丁格尔玫瑰图
pie = Pie(init_opts=opts.InitOpts(width='800px', height='600px', bg_color='white'))
pie.add(
    '', [list(z) for z in zip(list(reversed(list(df_overseas['country']))), sorted(list(df_overseas['area'])))],
    radius=['25%', '80%'], center=['50%', '50%'], rosetype="area",
    itemstyle_opts=opts.ItemStyleOpts(border_width=1, border_color='white'),
    label_opts=opts.LabelOpts(formatter="{b}", position='inside', color='white', font_size=8, font_weight='bolder')
).set_global_opts(
    title_opts=opts.TitleOpts(title='深圳境外输入\n   确诊病例', pos_left='44%', pos_top='43%',
               title_textstyle_opts=opts.TextStyleOpts(color='rgb(43, 70, 213)', font_size=14)),
    legend_opts=opts.LegendOpts(is_show=False)
).render('overseas1.html')

在这里插入图片描述

代码要点介绍:

  • 使用area模式:rosetype参数设置为area,所有扇形圆心角相同,仅通过半径展现数据大小。

  • 绘图半径调整:原始数据中最大的数是1234,最小的数是1,差距太大。如果按照数据大小来展示玫瑰图的半径,数据为1的组看不到图形。
    所以代码中先提取了数据中非重复的值,然后给每个非重复值从50开始递增设置绘图的半径高度。

  • 调整显示比例:运行代码,如果结果显示的范围与原图的差异很大,则调整半径等数据。

设置图形颜色和内部环形

玫瑰图的形状绘制好后,继续设置颜色等其他部分。

# 根据不重复的数据,生成图形的颜色值
gap1, gap2 = 7, 14
color_graph = [v for v in range(60, 60+gap1*(len(current_no_repeat)//2), gap1)] + \
              [v for v in range(60+gap1*(len(current_no_repeat)//2), 60+gap1*(len(current_no_repeat)//2) +
                                gap2*(len(current_no_repeat)-len(current_no_repeat)//2), gap2)]
color_dict = {k: v for k, v in zip(current_no_repeat, sorted(color_graph, reverse=True))}
color = ['rgb({a},{a},{a})'.format(a=color_dict[v[0]]) if v[1] == 0 else 'rgb(43, 70, 213)' for v in data.values()]

pie = Pie(init_opts=opts.InitOpts(width='800px', height='600px', bg_color='white'))
pie.add(
    '', [list(z) for z in zip(list(reversed(list(df_overseas['country']))), sorted(list(df_overseas['area'])))],
    radius=['25%', '80%'], center=['50%', '50%'], rosetype="area",
    itemstyle_opts=opts.ItemStyleOpts(border_width=1, border_color='white'),
    label_opts=opts.LabelOpts(formatter="{b}", position='inside', color='white', font_size=8, font_weight='bolder')
    # label_opts=opts.LabelOpts(is_show=False)
).add(
    '', [list(z) for z in zip([1], [1])],
    radius=['24%', '25.5%'], center=['50%', '50%'],
    itemstyle_opts=opts.ItemStyleOpts(color='rgb(43, 70, 213)'),
    label_opts=opts.LabelOpts(is_show=False)
).add(
    '', [list(z) for z in zip([1], [1])],
    radius=['22%', '22.5%'], center=['50%', '50%'],
    itemstyle_opts=opts.ItemStyleOpts(color='rgb(43, 70, 213)'),
    label_opts=opts.LabelOpts(is_show=False)
).set_global_opts(
    title_opts=opts.TitleOpts(title='深圳境外输入\n   确诊病例', pos_left='44%', pos_top='43%',
               title_textstyle_opts=opts.TextStyleOpts(color='rgb(43, 70, 213)', font_size=14)),
    legend_opts=opts.LegendOpts(is_show=False)
).set_colors(
    list(reversed(color))
).render('overseas.html')

在这里插入图片描述
代码要点介绍:

  • 颜色渐变设置:原图中的颜色由渐变的灰色构成,如果新增病例大于0,则对应的扇形变为蓝色。
    灰色是RGB三原色都相等的颜色,代码中用两个变量gap1和gap2来调整颜色值的渐变,蓝色用取色器从原图中获取其颜色值。
  • 玫瑰图内部环形:在Pie对象绘制主图形的后面继续链式调用add()方法,在内部绘制两个环形图,调整大小和颜色等参数满足要求。
  • 调整标题的位置:设置标题的位置、颜色,使其显示在图形的中间。

绘制的图形和原图对比:

在这里插入图片描述

整体上对比,图形一样了,但图形里的数据标签位置不一样。

用办公软件处理数据标签

我用pyecharts设置标签时,调试了很多时间,都没有完成原图中的效果。

所以我推测,原图的标签不是用代码完成的,原因为:

  • 原图中的国家名和数据的位置不统一,大小等格式也不一样。标签设置时使用富文本rich参数也基本实现不了。
  • 绘图的数据不是病例数据,而是处理后的半径高度数据,标签设置时使用formatter参数无法传入绘图外的数据。

所以,我将数据标签隐藏了,然后手动用办公软件给图形加数据标签,结果如下:

在这里插入图片描述
总结

本文以深圳卫健委中的图形为例,实践如何用Python画展示病例的南丁格尔玫瑰图。

如果文中有不妥之处,欢迎指正,如果本文对你有帮忙,欢迎点赞、在看和分享。

相关阅读
循序渐进,学会用pyecharts绘制玫瑰图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小斌哥ge

非常感谢,祝你一切顺利。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值