Python-matplotlib绘制双(多)y轴图像

一:灵感问题(难点)

        在利用python中的matplotlib绘制双y轴图像(条形图+折线图)过程中,为了防止折线图被条形图遮挡,我们需要先绘制条形图,而后绘制折线图,大致效果图如下:

        (这里为了看得更清楚对一些线条做了加宽处理)

        这里我们可以发现:先画的条形图默认使用了左侧的y轴,而后画的折线图默认使用了右侧的y轴。但个人看图习惯加上强迫症想让后画的折线图使用的y轴在左侧,而先画的条形图使用的y轴在右侧,这该如何调整?

二:调整思路

        前期的一些绘制双y轴图像所需要的基础代码:导入模块-修改字体-输入统计数据-创建图像对象-添加子图(创建轴对象);

# import the module needed
from matplotlib import pyplot as plt
from matplotlib import font_manager# adjust the font
my_font = font_manager.FontProperties(fname="C:/Windows/Fonts/msyh.ttc")# module.property(parameter-path)# input the data
year = list(range(2008, 2023))  
num = [25, 32, 28, 22, 24, 26, 9, 10, 18, 16, 16, 11, 14, 16, 13]
loss = [192.24, 84.97, 65.79, 48.81, 126.29, 152.45, 135.78,72.18, 45.94, 55.77, 44.56, 116.38, 8.10, 24.67, 23.79]  # 创建一个空白图像对象
fig = plt.figure(figsize=(13, 7), dpi=80)# 添加子图(创建轴对象)
# 创建后会默认显示一个0-1的坐标轴,即使没有绘制任何内容
axis_1 = fig.add_axes((0.1, 0.1, 0.8, 0.8))# rect-tuple(left, bottom, width, height) # 0.1-0.1-0.8-0.8为平时作图默认的轴位置
axis_2 = axis_1.twinx()  # 在axis_1基础上创建新的轴对象,共用x轴绘制不同的数据集

1.调整作图顺序及透明度

        调整作图顺序:先画折线图,后画条形图,使得折线图使用左侧y轴,条形图使用右侧y轴;

        调整透明度:绘制条形图时修改alpha参数,调整透明度,削弱条形图对折线图的遮挡效果;

# 绘制year-num数据集(折线图)
axis_1.plot(year, num, color="#6AA84F", marker="o", linewidth=2)# 绘制year-loss数据集(条形图)
axis_2.bar(year, loss, color="#5470C6", alpha=0.8)# 设置坐标轴颜色
plt.gca().spines["left"].set_color("#6AA84F")
plt.gca().spines["right"].set_color("#5470C6")# 设置坐标轴轴线宽度
plt.gca().spines["left"].set_linewidth(2)
plt.gca().spines["right"].set_linewidth(2) 

        按上述方式调整的最终大致效果图如下:

        这里我们可以发现:图像基本达到我们想要的效果,但这样损失了条形图的可见度,折线图被遮挡的效果也并没有完全消除,有没有更好的办法?

2.调整轴对象对应关系  

        为了彻底消除折线图被条形图遮挡的情况,我们还是采用先画条形图,后画折线图的方式;

axis_1.bar(year, loss, color="#5470C6")
axis_2.plot(year, num, color="#6AA84F", marker="o", linewidth=2)

        但这一次我们先使用axis_2轴对象,绘制条形图,再用轴对象axis_1,绘制折线图,更改轴对应关系重新绘图,让条形图使用axis_2对应的右侧y轴,让折线图使用axis_1对应的左侧y轴:

# 更改轴对应关系
# 绘制year-loss数据集(条形图),使用axis_2
axis_2.bar(year, loss, color="#5470C6")
# 绘制year-num数据集(折线图),使用axis_1
axis_1.plot(year, num, color="#6AA84F", marker="o", linewidth=2)

        我们发现:的确,折线图如愿用到了左侧的y轴,条形图用到了右侧的y轴,但同时,非常奇怪的是,后绘制的折线图居然被先绘制的条形图所遮挡,这是为什么?

        这里我先想到的原因是图层原因:先创建的axis_1图层在底层,后创建的axis_2图层在顶层;于是拿着代码问了下AI,AI十分肯定地回答了我这只与绘图顺序有关,与轴对象创建顺序无关!

        这样子又绕了一大圈,试着加入参数zorder什么的都没有效果(我觉得应该是不适用于这种双y轴图像的绘制),又绕了回来,按照最开始的想法自己调试代码找一下原因:

        当仅创建一个轴对象时:

axis_1 = fig.add_axes((0.1, 0.1, 0.8, 0.8))
plt.gca().spines["left"].set_color("r")  # 左侧坐标轴标红
plt.title("仅创建一个轴对象axis_1", fontproperties=my_font, size=17)

        当创建两个轴对象时:

axis_1 = fig.add_axes((0.1, 0.1, 0.8, 0.8))
plt.gca().spines["left"].set_color("r")  # 左侧坐标轴标红
axis_2 = axis_1.twinx()
plt.gca().spines["right"].set_color("b")  # 右侧坐标轴标蓝
plt.title("创建两个轴对象axis_1、axis_2", fontproperties=my_font, size=17)

        我们发现:axis_1标红的左侧坐标轴不见了,是被覆盖了吗?

        越发肯定图层问题,修改代码验证:

axis_1 = fig.add_axes((0.1, 0.1, 0.8, 0.8))
plt.gca().spines["left"].set_color("r")  # 左侧坐标轴标红
axis_2 = axis_1.twinx()
plt.gca().spines["right"].set_color("b")  # 右侧坐标轴标蓝
plt.gca().spines["left"].set_visible(False)  # 隐藏左侧坐标轴
plt.title("创建两个轴对象axis_1、axis_2并隐藏axis_2左侧坐标轴",fontproperties=my_font, size=17)

        我们发现:在axis_1中标红的左侧坐标轴重新显现,因此,最初的猜测是正确的:在图像对象fig下创建轴对象axis相当于在画布上创建图层,且先创建的轴对象图层在下,后创建的轴对象图层在上

        同时,在这次轴对象创建的验证猜想过程中,也发现对于函数plt.gca()的一些误读:plt.gca()函数的作用是获取当前的轴对象,因此不仅在上述创建两个轴对象并分别对两个轴对象的坐标轴进行标色过程中需要注意plt.gca()函数的调用位置,同时也意识到之前的画图中如调整思路1中对坐标轴进行标色时,连续调用两次plt.gca()函数的错误操作,以至于后续的一系列误导。

        整思路1中对坐标轴进行标色时,最初的认识是:创建的两个轴对象,axis_1只有左侧纵坐标轴,axis_2只有右侧纵坐标轴,(但实际上都有,只是另一侧没有刻度),因此在创建完两个轴对象后,连续调用两次plt.gca()函数对左右纵坐标轴标色,即axis_1的左侧纵坐标轴,axis_2的右侧纵坐标轴,(但实际上是对当前轴对象也就是axis_2的左右两侧纵坐标轴进行了标色),却也误打误撞呈现出了想要的纵坐标轴标色效果。

        因此,将plt.gca().spines直接替换为指定轴对象如axis_1.spines会更加清晰明确。

        最后,认识到了先后创建轴对象所带来的的图层上下关系,那么更改作图时轴对象对应关系必然会带来图像遮挡,无法达到要求

3.调整坐标轴位置

        在上次的思路中认识到了可以指定轴对象进行坐标轴标色、坐标轴隐藏等效果后,既然无法让图像对应到想要位置的坐标轴,是否可以通过移动坐标轴到达想要的位置?

        最终思路3也是完美的达到了想要的效果,这里直接借思路3的回顾过程直接完整的描述整个解决过程和代码:

        前期的基础工作代码还是一样,在这之后对所需轴对象的坐标轴进行位置移动,并进行坐标轴颜色和轴线宽度的设置以便让观看效果更佳:

# 调整坐标轴位置
axis_1.spines["left"].set_position(("axes", 1))
axis_2.spines["right"].set_position(("axes", 0))# 调整坐标轴颜色
axis_1.spines["left"].set_color("#5470C6")
axis_2.spines["right"].set_color("#6AA84F")# 设置坐标轴轴线宽度
axis_1.spines["left"].set_linewidth(2)  # 设置左边坐标轴线宽度为2
axis_2.spines["right"].set_linewidth(2)  # 设置右边坐标轴线宽度为2

         完成上述工作后简单画图发现:坐标轴的颜色显示比较怪异,存在遮挡效果,且坐标轴刻度看着十分别扭,对此进行进一步完善:

# 由于图层关系,隐藏轴对象的另一侧坐标轴
axis_1.spines["right"].set_visible(False)  # 非必要,因为axis_1图层在下,不隐藏也会被覆盖
axis_2.spines["left"].set_visible(False)  # 必要,axis_2图层在上,不隐藏会遮挡axis_1坐标轴颜色# 调整坐标轴刻度位置
axis_1.yaxis.set_ticks_position("right")
axis_2.yaxis.set_ticks_position("left")

        最后,画出符合自我要求的图像:

# 绘制year-loss数据集(条形图),使用axis_2
axis_1.bar(year, loss, color="#5470C6")# 绘制year-num数据集(折线图),使用axis_1
axis_2.plot(year, num, color="#6AA84F", marker="o", linewidth=2)# 展示图像
plt.show()

        当然,还可以进行调整坐标轴标签,添加图例,调整坐标轴刻度范围等等一系列操作进一步完善图像,让图像表现的信息更加多样全面。

        由此进一步添加描述信息对我国2008至2022年风暴潮危害发生次数及经济损失进行简单的数据统计和可视化操作:

# 绘制year-loss数据集(条形图),使用axis_2
axis_1.bar(year, loss, color="#5470C6", label="损失(亿元)")# 进一步完善axis_1图像信息
axis_1.set_xlabel("年份", fontproperties=my_font, size=17)  # 加入size参数调节坐标轴信息字体大小
axis_1.set_ylabel("损失(亿元)", fontproperties=my_font, size=17, color="#5470C6")  # 设置轴标签
axis_1.yaxis.set_label_position("right")  # 调整y轴标签位置
axis_1.legend(prop=my_font, loc="upper center", bbox_to_anchor=(0.7, 0.77))# 加入参数调整legend位置,(1,1)为右上角# 绘制year-num数据集(折线图),使用axis_1
axis_2.plot(year, num, color="#6AA84F", label="发生次数", marker="o", linewidth=2)# 进一步完善axis_2图像信息
axis_2.set_ylabel("发生次数", fontproperties=my_font, size=17, color="#6AA84F")
axis_2.yaxis.set_label_position("left")
axis_2.legend(prop=my_font, loc="right")  # 要在绘图函数中加入label参数# 两个轴对象共用描述信息
plt.xticks(year)  # 调整坐标轴刻度
plt.title("2008-2022风暴潮危害发生次数及经济损失统计", fontproperties=my_font, size=20, color="m")

三:整体回顾

        以上整个灵感问题来自天马行空,整个调整和解决思路也都是基于个人低水平的角度,感觉整个回顾下来还是有些没有表述清楚,逻辑不太明确,写的也有些冗余,一起交流,共同进步。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

首次安装Mysql数据库

1、在mysql官网下载自己需要的版本 2、选择安装类型 3、 检查一下需求版本 4、 这里可能会弹出如下信息,先不用管这一步,点击Yes继续即可 5、 安装需要的环境,点击执行就可以,此过程会比较慢 如下就是全面安装完成了,点…

《Linux 简易速速上手小册》第8章: 安全性与加固(2024 最新版)

文章目录 8.1 防火墙与安全策略8.1.1 重点基础知识8.1.2 重点案例:配置 iptables 以保护 Web 服务器8.1.3 拓展案例 1:使用 firewalld 配置动态防御区域8.1.4 拓展案例 2:配置 ufw 以简化管理 8.2 SSH 安全最佳实践8.2.1 重点基础知识8.2.2 重…

从基建发力,CESS 如何推动 RWA 发展?

2023 年 11 月 30 日,Web3 基金会(Web3 Foundation)宣布通过 Centrifuge 将部分资金投资于 RWA(Real World Assets,真实世界资产),试点投资为 100 万美元。Web3 基金会旨在通过支持专注于隐私、…

可视化工具:将多种数据格式转化为交互式图形展示的利器

引言 在数据驱动的时代,数据的分析和理解对于决策过程至关重要。然而,不同的数据格式和结构使得数据的解读变得复杂和困难。为了解决这个问题,一种强大的可视化工具应运而生。这个工具具有将多种数据格式(包括JSON、YAML、XML、C…

每日一题 (不用加减乘除做加法,找到数组中消失的数字)

不用加减乘除做加法_牛客题霸_牛客网 (nowcoder.com) 可以使用位运算符实现两个整数的加法: 在二进制加法中,我们通常使用“逐位相加”的方法来模拟常规加法的过程。当两个数字进行加法运算时,从最低位(通常是右侧)开…

Roop的安装教程

roop插件的安装,并不容易 并且最好就是在电脑本地完成,因为涉及到C、visual studio软件,并且还需要在电脑本地放置一些模型,用autoDL其实也有镜像,但是需要数据扩容至少100G,烧钱。。。 电脑本地&#xff0…

000——对i.MAX6uLL进行开箱检查

目录 00外观检查 01有线网卡检查 02USB-host测试 03耳机测试 04按键测试 05查看CPU温度 00外观检查 看起来没什么问题,买了半年了刚开始要做 01有线网卡检查 开机启动正常,韦东山老师还写了个欢迎界面,这个我后面因为要用于毕业设计&am…

一、Docker/安装包部署ClickHouse

Docker/安装包部署ClickHouse 一、docker部署1.安装Docker2.拉取ClickHouse镜像2.1 选择拉取版本2.2 拉取镜像 3.启动ClickHouse3.1 确定好挂载目录3.2 测试环境3.3 生产环境3.1.1 获取配置文件3.1.2 配置文件中添加用户3.1.3 启动容器 4.使用DBeaver连接 二、安装包安装1.准备…

Python基于大数据的电影预测分析系统

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

Linux:搭建docker私有仓库(registry)

当我们内部需要存储镜像时候,官方提供了registry搭建好直接用,废话少说直接操作 1.下载安装docker 在 Linux 上安装 Docker Desktop |Docker 文档https://docs.docker.com/desktop/install/linux-install/安装 Docker 引擎 |Docker 文档https://docs.do…

PKI - 借助Nginx实现_客户端使用CA根证书签发客户端证书

文章目录 Pre概述步骤1. 创建根证书2. 生成客户端证书3. 准备客户端证书扩展文件4. 签发客户端证书5. 配置Nginx5. 重启 Nginx6. 测试 SAN 证书扩展案例:使用IP访问 Pre PKI - 借助Nginx 实现Https 服务端单向认证、服务端客户端双向认证 PKI - 数字签名与数字证书…