比较(六)利用python绘制径向柱图

news2024/11/15 21:57:57

比较(六)利用python绘制径向柱图

径向柱图(Circular Barplot)简介

1

径向柱图基于同心圆网格来绘制条形图,虽然不如普通条形图表达准确,但却有抓人眼球的效果。其衍生的南丁格尔玫瑰图则广为人知。

快速绘制

  1. 基于matplotlib

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.cm as cm
    
    np.random.seed(0)  # 设置随机种子为0
    
    # 自定义数据
    df = pd.DataFrame(
            {
                'Name': ['item ' + str(i) for i in list(range(1, 51)) ],
                'Value': np.random.randint(low=10, high=100, size=50)
            })
    
    # 初始化布局-极坐标图
    plt.figure(figsize=(10,8))
    ax = plt.subplot(111, polar=True)
    
    # 移除网格
    plt.axis('off')
    
    # 坐标限制
    upperLimit = 100
    lowerLimit = 30
    
    # 计算极值
    max_value = df['Value'].max()
    
    # 数据缩放
    slope = (max_value - lowerLimit) / max_value
    heights = slope * df.Value + lowerLimit
    
    # 计算每个条形的宽度
    width = 2*np.pi / len(df.index)
    
    # 计算角度
    indexes = list(range(1, len(df.index)+1))
    angles = [element * width for element in indexes]
    angles
    
    # 增加条形图
    bars = ax.bar(
        x=angles, 
        height=heights, 
        width=width, 
        bottom=lowerLimit,
        linewidth=2, 
        edgecolor="white",
        color="#61a4b2",)
    

    2

定制多样化的径向柱图

自定义径向柱图一般是结合使用场景对相关参数进行修改,并辅以其他的绘图知识。参数信息可以通过官网进行查看,其他的绘图知识则更多来源于实战经验,大家不妨将接下来的绘图作为一种学习经验,以便于日后总结。

  1. 添加标签

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.cm as cm
    
    np.random.seed(0)  # 设置随机种子为0
    
    # 自定义数据
    df = pd.DataFrame(
            {
                'Name': ['item ' + str(i) for i in list(range(1, 51)) ],
                'Value': np.random.randint(low=10, high=100, size=50)
            })
    
    # 初始化布局-极坐标图
    plt.figure(figsize=(10,8))
    ax = plt.subplot(111, polar=True)
    
    # 移除网格
    plt.axis('off')
    
    # 坐标限制
    upperLimit = 100
    lowerLimit = 30
    
    # 计算极值
    max_value = df['Value'].max()
    
    # 数据缩放
    slope = (max_value - lowerLimit) / max_value
    heights = slope * df.Value + lowerLimit
    
    # 计算每个条形的宽度
    width = 2*np.pi / len(df.index)
    
    # 计算角度
    indexes = list(range(1, len(df.index)+1))
    angles = [element * width for element in indexes]
    angles
    
    # 添加条形图
    bars = ax.bar(
        x=angles, 
        height=heights, 
        width=width, 
        bottom=lowerLimit,
        linewidth=2, 
        edgecolor="white",
        color="#61a4b2",
    )
    
    # 标签和bar的间距定义
    labelPadding = 4
    
    # 添加标签
    for bar, angle, height, label in zip(bars,angles, heights, df["Name"]):
    
        # 弧度转化:将弧度转为度,如np.pi/2->90
        rotation = np.rad2deg(angle)
    
        # 颠倒一部分标签,方便查看
        alignment = ""
        if angle >= np.pi/2 and angle < 3*np.pi/2:
            alignment = "right"
            rotation = rotation + 180
        else: 
            alignment = "left"
    
        # 通过text函数添加标签
        ax.text(
            x=angle, 
            y=lowerLimit + bar.get_height() + labelPadding, 
            s=label, 
            ha=alignment, 
            va='center', 
            rotation=rotation, 
            rotation_mode="anchor") 
    

    3

  2. 引申-简单绘制南丁格尔玫瑰图

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.cm as cm
    
    np.random.seed(0)  # 设置随机种子为0
    
    # 自定义数据
    df = pd.DataFrame(
            {
                'Name': ['item ' + str(i) for i in list(range(1, 51)) ],
                'Value': np.random.randint(low=10, high=100, size=50)
            })
    # 排序
    df = df.sort_values(by=['Value'])
    
    # 初始化布局
    plt.figure(figsize=(10,8))
    ax = plt.subplot(111, polar=True)
    plt.axis('off')
    
    # 坐标限制
    upperLimit = 100
    lowerLimit = 30
    
    # 高度
    heights = df.Value
    # 计算每个条形的宽度
    width = 2*np.pi / len(df.index)
    
    # 颜色
    cmap = cm.RdYlGn
    # 归一化
    norm_heights = (heights - np.min(heights)) / (np.max(heights) - np.min(heights))
    # 颜色映射到heights
    colors = cmap(norm_heights)
    
    
    # 计算角度
    indexes = list(range(1, len(df.index)+1))
    angles = [element * width + 0.5*np.pi for element in indexes] # 指定从0开始逆时针旋转
    
    
    # 添加条形图
    bars = ax.bar(
        x=angles, 
        height=heights, 
        width=width, 
        bottom=lowerLimit,
        linewidth=2, 
        edgecolor="white",
        color=colors,
    )
    
    # 标签和bar的间距定义
    labelPadding = 4
    
    # 添加标签
    for bar, angle, height, label in zip(bars,angles, heights, df["Name"]):
    
        # 弧度转化:将弧度转为度,如np.pi/2->90
        rotation = np.rad2deg(angle)
    
        # 颠倒一部分标签,方便查看
        alignment = ""
        if angle >= np.pi/2 and angle < 3*np.pi/2:
            alignment = "right"
            rotation = rotation + 180
        else: 
            alignment = "left"
    
        # 通过text函数添加标签
        ax.text(
            x=angle, 
            y=lowerLimit + bar.get_height() + labelPadding, 
            s=label, 
            ha=alignment, 
            va='center', 
            rotation=rotation, 
            rotation_mode="anchor")
    

    4

  3. 分组径向柱图

    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    
    rng = np.random.default_rng(123) # 随机种子
    
    # 自定义数据
    df = pd.DataFrame({
        "name": [f"item {i}" for i in range(1, 51)],
        "value": rng.integers(low=30, high=100, size=50),
        "group": ["A"] * 10 + ["B"] * 20 + ["C"] * 12 + ["D"] * 8
    })
    
    # 自定义函数,将上述的弧度转换、添加标签抽象成函数
    def get_label_rotation(angle, offset):
        '''
        输入弧度和偏移量,返回对应的角度rotation以及对齐方式alignment
        '''
        rotation = np.rad2deg(angle + offset)
        if angle <= np.pi:
            alignment = "right"
            rotation = rotation + 180
        else: 
            alignment = "left"
        return rotation, alignment
    
    
    def add_labels(angles, values, labels, offset, ax):
        
        # 标签与bar的间距
        padding = 4
        
        # 迭代每个弧度、bar值和标签
        for angle, value, label, in zip(angles, values, labels):
            angle = angle
            
            # 获取角度和对齐方式
            rotation, alignment = get_label_rotation(angle, offset)
    
            # 添加文本标签
            ax.text(
                x=angle, 
                y=value + padding, 
                s=label, 
                ha=alignment, 
                va="center", 
                rotation=rotation, 
                rotation_mode="anchor"
            ) 
    
    # 自定义基础变量
    GROUP = df["group"].values # 分组
    GROUPS_SIZE = [len(i[1]) for i in df.groupby("group")] # 每组的数量
    COLORS = [f"C{i}" for i, size in enumerate(GROUPS_SIZE) for _ in range(size)] # 每组使用不同的颜色
    
    # bar的值与标签
    VALUES = df["value"].values
    LABELS = df["name"].values
    
    # 偏移量:默认从0开始,指定成从90度位置开始
    OFFSET = np.pi / 2
    
    # bar宽度、角度
    PAD = 3 # 每组末尾添加3个空白bar
    ANGLES_N = len(VALUES) + PAD * len(np.unique(GROUP))
    ANGLES = np.linspace(0, 2 * np.pi, num=ANGLES_N, endpoint=False)
    WIDTH = (2 * np.pi) / len(ANGLES) # 2pi/条形数量得到每个条形宽度
    
    # 获取索引
    offset = 0
    IDXS = []
    for size in GROUPS_SIZE:
        IDXS += list(range(offset + PAD, offset + size + PAD))
        offset += size + PAD
    
    # 初始化极坐标图
    fig, ax = plt.subplots(figsize=(10, 8), subplot_kw={"projection": "polar"})
    
    # 指定偏移量
    ax.set_theta_offset(OFFSET)
    
    # 设置范围
    ax.set_ylim(-100, 100)
    
    # 移除边框
    ax.set_frame_on(False)
    
    # 移除网格和轴刻度
    ax.xaxis.grid(False)
    ax.yaxis.grid(False)
    ax.set_xticks([])
    ax.set_yticks([])
    
    
    # 添加条形图
    ax.bar(
        ANGLES[IDXS], VALUES, width=WIDTH, color=COLORS, 
        edgecolor="white", linewidth=2
    )
    
    # 添加标签
    add_labels(ANGLES[IDXS], VALUES, LABELS, OFFSET, ax)
    
    # 额外添加分组标签
    offset = 0 # 重置为0
    for group, size in zip(["A", "B", "C", "D"], GROUPS_SIZE):
        # 在条形图下添加线条
        x1 = np.linspace(ANGLES[offset + PAD], ANGLES[offset + size + PAD - 1], num=50)
        ax.plot(x1, [-5] * 50, color="#333333")
        
        # 添加分组标签
        ax.text(
            np.mean(x1), -20, group, color="#333333", fontsize=14, 
            fontweight="bold", ha="center", va="center"
        )
        
        # 添加参考线:[20, 40, 60, 80]
        x2 = np.linspace(ANGLES[offset], ANGLES[offset + PAD - 1], num=50)
        ax.plot(x2, [20] * 50, color="#bebebe", lw=0.8)
        ax.plot(x2, [40] * 50, color="#bebebe", lw=0.8)
        ax.plot(x2, [60] * 50, color="#bebebe", lw=0.8)
        ax.plot(x2, [80] * 50, color="#bebebe", lw=0.8)
        
        offset += size + PAD
    

    5

总结

以上通过matplotlib结合极坐标绘制基本的径向柱图,并结合相关绘图方法绘制南丁格尔玫瑰图和分组径向柱图。

共勉~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1906916.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

可编程直流电源的恒压模式(CV)和恒流模式(CC)

本文介绍可编程直流电源的恒压模式&#xff08;CV&#xff09;和恒流模式&#xff08;CC&#xff09;。 可编程直流电源在硬件开发过程中经常被用到&#xff0c;通常&#xff0c;它有2种模式&#xff0c;恒压模式&#xff08;CV&#xff09;和恒流模式&#xff08;CC&#xff…

合并pdf的方法,如何合并pdf文件到一个pdf,简单方法

在现代办公和学习中&#xff0c;pdf格式的文件因其跨平台兼容性和安全性得到了广泛应用。然而&#xff0c;有时我们需要将多个pdf文件合并成一个&#xff0c;以便于管理和分享。本文将详细介绍几种合并pdf的方法&#xff0c;帮助读者轻松完成pdf文件的合并工作。 方法一、使用p…

uboot镜像之boot烧写

适用场景:单板上没有boot&#xff0c;和按地址烧写配合&#xff0c;可完成单板所有镜像的烧写。 原理:bootrom读取u-boot.bin至内存并执行此u-boot 然后运行uboot,通过uboot sf命令烧录uboot.bin到flash存储空间去. bootrom读取u-boot.bin至内存并执行此u-boot 通过uboot sf命…

java-数据结构与算法-02-数据结构-03-递归

1. 概述 定义 计算机科学中&#xff0c;递归是一种解决计算问题的方法&#xff0c;其中解决方案取决于同一类问题的更小子集 In computer science, recursion is a method of solving a computational problem where the solution depends on solutions to smaller instances…

swiftui中封装一个carditem视图,结合toolbar实现滚动的瀑布流,仿小红书首页

实现的效果如上图所示&#xff0c;支持左右滑动切换页面&#xff0c;也支持点击顶部的toolbar菜单切换页面&#xff0c;每个页面里面的每一项都是一个carditem.swift&#xff0c;这是我封装的一个card组件&#xff0c;用于展示每一个card内容&#xff0c;carditem.swift内容如下…

【Altium】AD-网络版一个用户非人为异常占用多个License的解决方法

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 当出现一个用户同时占用多个授权&#xff0c;又无法单独释放一个授权的情况下&#xff0c;该如何解决。 2、 问题场景 一个用户获取网络版授权后&#xff0c;AD会自动重复获取授权&#xff0c;直到该license下所有授…

Qt 线程 QThread类详解

Qt 线程中QThread的使用 在进行桌面应用程序开发的时候&#xff0c; 假设应用程序在某些情况下需要处理比较复杂的逻辑&#xff0c; 如果只有一个线程去处理&#xff0c;就会导致窗口卡顿&#xff0c;无法处理用户的相关操作。这种情况下就需要使用多线程&#xff0c;其中一个…

盲盒小程序开发:互联网下的的盲盒发展

近些年来&#xff0c;盲盒行业发展的非常迅速&#xff0c;盲盒的不确定性吸引了无数玩家&#xff0c;盲盒的市场规模逐渐扩大&#xff0c;盲盒品牌也在不断出现&#xff0c;为盲盒消费者带来更多的新鲜体验&#xff0c; 随着互联网小程序的的快速发展&#xff0c;盲盒小程序为…

告别‘找文件’大战,可道云teamOS分区管理,文件秒定位

在数字化时代&#xff0c;数据已经成为企业最宝贵的资产之一。 如何高效、安全地管理这些数据&#xff0c;成为了每一个企业必须面对的问题。 企业网盘作为一种便捷的数据存储和共享工具&#xff0c;已经成为了企业日常运营中不可或缺的一部分。 然而&#xff0c;传统的网盘管…

人员定位系统于不同场景的实际应用

人员定位系统的应用&#xff0c;尽管还没有做到大范围的普及&#xff0c;但是这一系统在不同企业&#xff0c;不同单位的实际应用效果还是很好的&#xff0c;所以人员定位系统也应用于不同场景当中了&#xff0c;那么&#xff0c;本文就来讲讲这一系统在不同场景的实际应用。 人…

汽车信息安全--欧盟汽车法规

目录 General regulation 信息安全法规 R155《网络安全及网络安全管理系统》解析 R156《软件升级与软件升级管理系统》解析 General regulation 欧洲的汽车行业受到一系列法律法规的约束&#xff0c;包括 各个方面包括&#xff1a; 1.安全要求&#xff1a;《通用安全条例&a…

【Qt】对话框

1、自定义对话框并赋予ui界面&#xff0c;用按钮呼出 https://www.bilibili.com/video/BV1rK411A7qi/?spm_id_from333.999.0.0&vd_sourcefd6555f02904e7fa85526a2ff4b8b66e 新建 - 文件和类 - Qt - Qt设计师界面类在原来的父窗口cpp文件中初始化新窗口并调用exec显示模态…

什么软件能够监控电脑?五大好用监控电脑软件推荐

在当今的企业管理中&#xff0c;电脑监控软件已经成为必不可少的工具。它们不仅能提升员工的工作效率&#xff0c;还能保护企业的核心数据&#xff0c;防止信息泄露。以下将介绍几款市场上备受好评的电脑监控软件&#xff0c;特别是固信软&#xff0c;帮助企业找到最适合的解决…

软件测试下的AI之路(5)

😏作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。 📡主页地址:【Austin_zhai】 🙆目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能,分享行业相关最新信息。 💎声明:博主日常工作较为繁忙,文章会不定期更新,各类行业或职场问题欢迎大家…

掌握MySQL基础命令:数据更新操作详细操作(数据的增删改)

MySQL数据修改是指使用SQL语句&#xff08;如UPDATE、INSERT、DELETE&#xff09;对数据库表中的数据进行更改、添加或删除的操作&#xff0c;常见的操作包括更新表中的记录、插入新记录以及删除现有记录 。 一、数据插入 1插入完整的数据记录 2插入非完整的数据记录 3插入多…

SQL 之 concat_ws和concat的区别

concat_ws和concat都是用于连接字符串的函数&#xff0c;但它们在使用上有一些区别&#xff1a; 一、concat、concat_ws函数格式&#xff1a; concat格式&#xff1a; concat&#xff08;参数1,参数2,…参数n&#xff09;&#xff0c;如果要加’分隔符’直接写在 各参数中间就…

【知网CNKI-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

【Git基本操作】创建本地仓库 | 配置本地仓库 | 认识工作区、暂存区、版本库、对象库 | add和commit操作

目录 1.创建Git本地仓库 1.1创建仓库 1.2创建和初始化Git本地仓库 1.3查看隐藏目录.git 2.配置本地仓库 2.1新增配置 2.2删除重置配置 2.3查看配置选项 2.4全局范围的新增和删除配置 3.工作区、暂存区、版本库、对象库 ​4.add操作和commit操作 4.1add操作 4.2com…

AI 大模型系统实战

AI 大模型是什么&#xff1f; 维基百科对基础模型的定义是这样的&#xff0c;基础模型是一种大型机器学习模型&#xff0c;通常在大量数据上进行大规模训练&#xff08;通过自监督学习或半监督学习&#xff09;&#xff0c;以使它可以适应各类下游任务。因此&#xff0c;它需要…

从入门到精通:Shopee,lazada,temu自养号测评成本、步骤、技巧详解

测评对于卖家来说是一种成本低回报快的推广方式&#xff0c;可以减少高额的平台广告费用&#xff0c;因此是一种很好的辅助手段&#xff0c;对商品的曝光、流量、转化和权重等方面起到了很好的辅助作用 建议还是自己精养一批账号&#xff0c;账号在自己手里比较安全可控&#…