• 如何用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]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    原始数据用字典的方式录入,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')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    代码要点介绍:

    • 使用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')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

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

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

    绘制的图形和原图对比:

    在这里插入图片描述

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

    用办公软件处理数据标签

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

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

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

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

    在这里插入图片描述
    总结

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

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

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

  • 相关阅读:
    CRM系统的客户细分有什么作用?
    element picker 时间控件,指定区间和指定月份置灰
    Redis集群(分布式缓存):详解持久化、主从同步原理、哨兵机制、Cluster分片集群,实现高并发高可用
    VUE [入门篇(三)]
    竞赛选题 深度学习疲劳驾驶检测 opencv python
    Vue:状态管理pinia
    git am冲突解决办法
    阿里云 ACK One 多集群管理全面升级:多集群服务、多集群监控、两地三中心应用容灾
    什么软件可以识别图片上的文字?分享三个实用的识别软件
    Scala 函数式编程02
  • 原文地址:https://blog.csdn.net/weixin_43790276/article/details/127432657