matplotlib可视化基础教程1: fig,ax绘图方式、图中图、坐标轴明细配置、子图间距调整等实用指南

475 阅读10分钟

背景介绍

大家好。之前给大家分享关于pandas的实战教程、python可视化教程,干货满满:

image.png 如果你想要系统和深入地了解学习pandas的语法和python可视化技巧,可以查看上面的文章。如果对你有帮助,还请关注下面公众号点赞关注转发~

大家好。之前给大家分享多篇关于python可视化技巧,今天给大家分享matplotlib库的基础教程,附带详细的代码和可视化结果,总结7种常见创建fig,ax的方法、5种绘制图中图、坐标轴各种配置总结、子图间距调整、子图关联等多种可视化技巧、新人小白也可以快速上手,干货满满。下面进入今天的主题~ 本文涉及的python库版本信息如下:

# !pip install mpl_font==1.1.0
# !pip install mplcyberpunk==0.7.1
import pandas as pd
from matplotlib import pyplot as plt
import mpl_font.noto
import numpy as np
import os
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.ticker as tick
import seaborn as sns
import warnings
warnings.filterwarnings("ignore"# 完全屏蔽所有警告
%matplotlib inline
print("matplotlib: ",mpl.__version__ ) # matplotlib:  3.7.5
print("pandas: ",pd.__version__)  # matplotlib:  3.7.5
print("seaborn: ",sns.__version__) # seaborn:  0.11.0

本文目录

创建画布fig和子图对象ax的方法汇总

什么是fig,axes,ax,plt,axis?

如下图所示;

整个图可以得到下面:

  • fig: 整个画布;
  • axes:画图ax的汇总;上图分别为axes[0],axes[1]。
  • ax: 子图ax(为画布fig中一个特定区域)
  • axis:具体的坐标轴;
  • plt: Pyplot为底层面向对象的绘图库提供状态机接口。状态机隐式自动创建图形和轴,以实现所需的绘图。

下面将给大家介绍在matplotlib库中常见总结fig,ax的方法函数。

方法1: 使用fig.add_axes创建fig和ax

# 定义fig
fig= plt.figure(figsize=(6,6), dpi=100)
# 自定义画布ax
ax1 = fig.add_axes([0.10.10.80.8])  # 散点图位置
ax2 = fig.add_axes([0.10.960.80.1])  # 边际分布图位置
ax3 = fig.add_axes([0.960.10.10.8])  # 边际分布图位置
plt.show()

方法2: 使用fig.add_subplot 创建fig和ax

# 定义fig
fig= plt.figure(figsize=(8,6), dpi=200)
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)

方法3: 使用plt.subplot2grid 创建fig和ax

# 绘制不规则的网格ax(空间布局)
ax = plt.subplot2grid((2,3),(0,0),rowspan=1, colspan=1)
ax = plt.subplot2grid((2,3),(1,0),rowspan=1, colspan=1,projection='polar')
ax = plt.subplot2grid((2,3),(0,1),rowspan=1, colspan=2# 使用一行2列的位置区间画图
fig = ax.get_figure()

方法4: 使用plt.subplots 创建fig和ax

fig, axes = plt.subplots(2,2)
ax1= axes[0,0#第一个位置的画布
ax2= axes[1,1#第4个位置的画布

方法5: 使用plt.subplot 创建fig和ax

ax= plt.subplot(221)
ax= plt.subplot(222)
fig= plt.gcf()

方法6 : 使用plt.add_subplot 创建fig和ax

from matplotlib.gridspec import GridSpec
fig = plt.figure()
gs = GridSpec(13)
ax = fig.add_subplot(gs[00])
ax.set_title("grid1")
ax = fig.add_subplot(gs[01:])
ax.set_title("grid2")
plt.show()

方法7 : 使用plt.subplot_mosaic 创建fig和ax

fig, axes = plt.subplot_mosaic([['upleft''right'],
                               ['lowleft''right']], layout='constrained')
axes['upleft'].set_title('upleft')
axes['lowleft'].set_title('lowleft')
axes['right'].set_title('right')
#通过ax获得fig
fig =ax.get_figure()
# 关闭fig
plt.close(fig)

绘制图中图方法总结

这里给大家总结如何在子图中绘制子图。

绘制放大图方法1: 使用mpl_toolkits的zoomed_inset_axes

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes
from mpl_toolkits.axes_grid1.inset_locator import mark_inset
# 生成一些数据
x = np.linspace(0101000)
y = np.sin(x)
# 创建主图
fig, ax = plt.subplots(figsize=(86))
# 绘制主图数据
ax.plot(x, y, label='Main Plot')

# 创建并配置放大图
axins = zoomed_inset_axes(ax, 1.5, loc='lower left',
                           bbox_to_anchor=(0.40.8,1, .5), # 锚点位置(x,y,width, height)相对图的相对位置
                         bbox_transform=ax.transAxes,
                         )  # 放大倍数为6倍,位置在右上角
axins.plot(x, y,c='r')  # 在放大图上再次绘制数据
# 设置放大图的x和y轴范围
x1, x2, y1, y2 = 2.530.30.5  # 指定局部放大区域
axins.set_xlim(x1, x2)
axins.set_ylim(y1, y2)
# 移除放大图的顶部和右侧边框
axins.spines['top'].set_visible(False)
axins.spines['right'].set_visible(False)
# axins.xaxis.set_ticks_position('bottom')
# axins.yaxis.set_ticks_position('left')
# 标记主图和放大图之间的关联
mark_inset(ax, axins, loc1=2, loc2=4, fc="none", ec="0.5")
# 显示图形
plt.show()

绘制放大图方法2:使用ax.indicate_inset_zoom绘制放大图

fig,ax = plt.subplots(figsize=(6,6))
ax.set_xlim(5, 10)
ax.set_ylim(0, 10)
ax1 = [6532#表示从ax2子图横坐标为6,纵坐标为5地方插入子图,宽度为3,高度为2

x1, x2, y1, y2 = 5.5,6.624 
axins = ax.inset_axes(
    [0.5, 0.5, 0.4, 0.4],
    xlim=(x1, x2), ylim=(y1, y2))
axins.set_facecolor('r')
ax.indicate_inset_zoom(axins, edgecolor="black")
axins.set_title("axins")
print(fig.axes, axins)
plt.show()

绘制图中图方法1:使用mpl_toolkits的inset_axes绘制放大图

from mpl_toolkits.axes_grid1.inset_locator import inset_axes
fig = plt.figure(figsize=[7.53.8])
ax = fig.add_subplot(121)
axins = inset_axes(ax, 
                   width="100%"#axins 显示宽度比例
                   height="100%",#axins 显示高度比例
                   bbox_to_anchor=(.2, .4, .6, .5), # 锚点位置(x,y,width, height)
                   bbox_transform=ax.transAxes,
                   loc='lower left' #显示的方向
                  )

# For visualization purposes we mark the bounding box by a rectangle
ax.add_patch(plt.Rectangle((.2, .4), .65, .55, ls="--", ec="c", fc="None",
                           transform=ax.transAxes))
ax.set(xlim=(010), ylim=(010))

绘制图中图方法2:使用ax.inset_axes绘制放大图

fig,ax = plt.subplots(figsize=(6,6))
ax.set_xlim(5, 10)
ax.set_ylim(0, 10)
coord = [6532#表示从ax2子图横坐标为6,纵坐标为5地方插入子图,宽度为3,高度为2
axines = ax.inset_axes(coord, transform = ax.transData) #因为是依据坐标刻度插入,使用的是ax2坐标刻度
axines.set_title("axines")
plt.show()

绘制图中图方法3:使用fig.add_axes来重叠法展示图中图

import matplotlib.pyplot as plt
import numpy as np
# 主图的数据
x = np.linspace(02*np.pi, 100)
y1 = np.sin(x)
# 创建主图
fig, ax = plt.subplots()
# 在主图上绘制数据
ax.plot(x, y1, label='Main Plot')
ax.legend(loc='lower left')
# 设置图中图的位置和大小
# 这里以左下角坐标(0.55, 0.65),宽高比为0.3和0.2为例
inset_ax = fig.add_axes([0.550.650.30.2], facecolor='none')
# 图中图的数据
y2 = np.cos(x)
# 在图中图上绘制数据
inset_ax.plot(x, y2, 'r', label='Inset Plot')
inset_ax.legend(loc='lower left')
# 可选地,可以调整图中图的坐标刻度、标签等
inset_ax.set_xlim([0, np.pi])
inset_ax.set_ylim([-1, 1])
inset_ax.set_xlabel('X Label in Inset')
inset_ax.set_ylabel('Y Label in Inset')
# 显示图形
plt.show()

子图ax坐标轴相关配置方法汇总

这里给大家介绍子图ax相关坐标轴显示配置

隐藏指定坐标轴&&刻度

from matplotlib.ticker import MultipleLocator,FormatStrFormatter
params = {"legend.fontsize"8,"legend.frameon":False'xtick.direction':'in''ytick.direction':'in'# 设置图例大小,是否透明,坐标轴朝向in朝内,out朝外。
with plt.rc_context(params):
    fig,ax= plt.subplots(figsize=(6,4))
    ax.set_xlabel('x [m]')
    # 隐藏指定坐标轴
    ax.spines["top"].set_visible(False# top,right,left,bottom
    ax.spines["right"].set_visible(False)

设置坐标轴朝向外面

from matplotlib.ticker import MultipleLocator,FormatStrFormatter
params = {"legend.fontsize"8,"legend.frameon":False'xtick.direction':'in''ytick.direction':'in'}
with plt.rc_context(params):
    fig,ax= plt.subplots(figsize=(6,4))
    ax.set_xlabel('x [m]')
    ax.spines["top"].set_visible(False) # top,right,left,bottom
    ax.spines["right"].set_visible(False)
     # 坐标轴朝向in朝内,out朝外,同时设置x轴和y轴的刻度方向
    ax.tick_params(direction='out', axis='both'

隐藏坐标轴但是显示刻度

from matplotlib.ticker import MultipleLocator,FormatStrFormatter
params = {"legend.fontsize"8,"legend.frameon":False'xtick.direction':'in''ytick.direction':'in'}
with plt.rc_context(params):
    fig,ax= plt.subplots(figsize=(6,4))
    ax.set_xlabel('x [m]')
    ax.spines["top"].set_visible(False# top,right,left,bottom
    ax.spines["right"].set_visible(False)
    ax.tick_params(direction='out', axis='both')  # 同时设置x轴和y轴的刻度方向
    ax.spines["left"].set_visible(False# top,right,left,bottom
    ax.axes.yaxis.set_visible(True)# 设置坐标轴刻度是否可见 xaxis, yaxis

将坐标轴显示在上面和右边

from matplotlib.ticker import MultipleLocator,FormatStrFormatter
params = {"legend.fontsize"8,"legend.frameon":False'xtick.direction':'in''ytick.direction':'in'}
with plt.rc_context(params):
    fig,ax= plt.subplots(figsize=(6,4))
    ax.set_xlabel('x [m]')
    ax.spines["top"].set_visible(True# top,right,left,bottom
    ax.spines["right"].set_visible(True)
    ax.tick_params(direction='out', axis='both')  # 同时设置x轴和y轴的刻度方向
    ax.spines["left"].set_visible(False# top,right,left,bottom
    ax.spines["bottom"].set_visible(False# top,right,left,bottom
    ax.axes.yaxis.set_visible(True)# 设置坐标轴刻度是否可见 xaxis, yaxis
    ax.axes.xaxis.tick_top()# 让x轴平移到上边
    ax.axes.yaxis.tick_right()#让y轴平移到右边
    ax.axes.yaxis.set_label_position('right'#设置y轴的标签到右边显示
    ax.axes.xaxis.set_label_position('top'#设置y轴的标签到右边显示
    ax.set_xlabel('x轴')
    ax.set_ylabel('y轴')

坐标轴逆序展示&&修改坐标轴标签

from matplotlib.ticker import MultipleLocator,FormatStrFormatter
params = {"legend.fontsize"8,"legend.frameon":False'xtick.direction':'in''ytick.direction':'in'}
with plt.rc_context(params):
    fig,ax= plt.subplots(figsize=(6,4))
    ax.set_xlabel('x [m]')
    ax.set_xlim(1,20) #设置坐标轴范围(1,100)
    ax.set_ylim(1,20) #设置坐标轴范围(1,100)
    ax.invert_yaxis() # 将y坐标轴进行逆序
    ticks = ax.set_xticks([1,6,9,13,20]) # 设置刻度
    labels = ax.set_xticklabels(['one','two','three','four','five'],ha='right',rotation = 30,fontsize = 'small'# 设置刻度标签

设置坐标轴的主刻度和副刻度

from matplotlib.ticker import MultipleLocator,FormatStrFormatter
params = {"legend.fontsize": 8,"legend.frameon":False, 'xtick.direction':'in''ytick.direction':'in'}
with plt.rc_context(params):
    fig,ax= plt.subplots(figsize=(10,4))
    ax.set_xlabel('x [m]')
    ax.set_xlim(1,20) #设置坐标轴范围(1,100)
    ax.set_ylim(1,20) #设置坐标轴范围(1,100)
    ax.xaxis.set_major_locatorMultipleLocator(2)) # 设置x轴主刻度的比例
    ax.xaxis.set_minor_locator(MultipleLocator(1)) # 设置x轴副刻度的比例
    ax.xaxis.set_minor_formatter(FormatStrFormatter('%0.2f')) # 设置x轴副刻度的展示格式
    ax.yaxis.set_major_locatorMultipleLocator(4)) # 设置x轴主刻度的比例
    ax.tick_params(which='major', length=12) # 设置主刻度的长度
    ax.tick_params(which='minor', length=4) # 设置副刻度的长度

一个图总结所有的配置

from matplotlib.ticker import MultipleLocator,FormatStrFormatter
params = {"legend.fontsize"8,"legend.frameon":False'xtick.direction':'in''ytick.direction':'in'}
with plt.rc_context(params):
    fig = plt.figure(layout='constrained', figsize=(10,4))
    fig.suptitle('这里是图标题')
    axes = fig.subplots(1,2)
    axes[0].set_xlabel('x [m]')
#     axes[0].spines["top"].set_visible(False) # top,right,left,bottom
    axes[0].spines["right"].set_visible(False)
    axes[0].spines["left"].set_visible(False)
    axes[0].spines["bottom"].set_visible(False)
    axes[0].tick_params(direction='out', axis='both')  # 同时设置x轴和y轴的刻度方向
    axes[0].axes.yaxis.set_visible(True)# 设置坐标轴刻度是否可见 xaxis, yaxis
    axes[0].axes.xaxis.tick_top()# 让x轴平移到上边
    axes[0].axes.yaxis.tick_right()#让y轴平移到右边
    axes[0].axes.yaxis.set_label_position('right') #设置y轴的标签到右边显示
    axes[0].axes.xaxis.set_label_position('top') #设置y轴的标签到右边显示
    axes[0].set_ylabel('可见刻度值')
    axes[0].set_title('子图1')
    
    axes[1].set_facecolor('red')
    axes[1].set_title('子图2')
    axes[1].set_xlabel('x轴')
    axes[1].set_ylabel('y轴')
    axes[1].invert_yaxis() # 将y坐标轴进行逆序
    axes[1].set_xlim(1,20) #设置坐标轴范围(1,100)
    axes[1].set_ylim(1,20) #设置坐标轴范围(1,100)
    ticks = axes[1].set_xticks([1,2,4,7,10]) # 设置刻度
    labels = axes[1].set_xticklabels(['one','two','three','four','five'],ha='right',rotation = 30,fontsize = 'small'# 设置刻度标签


    axes[1].xaxis.set_major_locator( MultipleLocator(2)) # 设置x轴主刻度的比例
    axes[1].xaxis.set_minor_locator(MultipleLocator(1)) # 设置x轴副刻度的比例
    axes[1].xaxis.set_minor_formatter(FormatStrFormatter('%0.2f')) # 设置x轴副刻度的展示格式
    axes[1].yaxis.set_major_locator( MultipleLocator(4)) # 设置x轴主刻度的比例
    axes[1].tick_params(which='major', length=12# 设置主刻度的长度
    axes[1].tick_params(which='minor', length=4# 设置副刻度的长度

综合应用展示

这里给大家分享

调节子图之间空间布局间距

plt.subplots_adjust()
fig.tight_layout()

fig= plt.figure(figsize=(8,6), dpi=200)
fig.subplots_adjust(left=0.1,
wspace=0.06,
hspace=0.16)
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)

效果展示:

子图之间添加备注

import numpy as np
import mpl_font.noto
import matplotlib.pyplot as plt
fig, axes = plt.subplots(12, figsize = (146))

axes[0].set_title("图A",fontsize = 20)#设置子图标题
#下面绘制子图2,绘制一个堆积柱状图
axes[1].set_title("图B",fontsize = 20)
#定义注释文本的样式
bbox_args = dict(boxstyle="round", fc="lightgreen")
#定义注释箭头的样式
arrow_args = dict(arrowstyle="<->",color='r')
#先把终点画在子图A上面
axes[0].annotate("终点", xy=(0.20.5),  xytext=(0.20.5),  ha="center", va="center", bbox=bbox_args, )
#把起点画在子图B上面,并设置跨图注释起点
axes[1].annotate("起点",
             xy=(0.20.5), xycoords=axes[0].transData,#跨子图设置,这里的意思是把xy的坐标转换为axes[0,0]的坐标
             xytext=(1.80.5),#开始点坐标这里(1.8, 0.5)就是以子图1坐标系下的坐标
             ha="left", va="bottom",
             bbox=bbox_args,
            arrowprops=dict(connectionstyle="arc3,rad=0.2",
                linewidth=2,        # 箭头线宽
                linestyle='--',      # 箭头线型
                facecolor='black',  # 箭头填充颜色
                edgecolor='black',  # 箭头边缘颜色
                alpha=0.2,     # 透明度
                **arrow_args,
                ))
plt.show()

子图之间fig,ax,plt转换

axes = fig.axes
fig=ax.get_figure()
fig =plt.gcf()
ax=  plt.gca()

设置fig和ax的背景颜色

fig = plt.figure(layout='constrained', facecolor='lightskyblue',figsize=(10,4))
fig.suptitle('here is Figure title')
figL, figR = fig.subfigures(12)
figL.set_facecolor('thistle')
axLes = figL.subplots(1,2)
axLes[1].set_xlabel('x [m]')
axLes[0].set_facecolor('red')
figL.suptitle('Left subfigure title')
figR.set_facecolor('paleturquoise')
axR = figR.subplots(12, sharey=True)
axR[0].set_title('Axes 1')
figR.suptitle('Right subfigure title')

保存图片为png,svg,pdf

fig.savefig("demo.png",dpi=300)
fig.savefig("demo.pdf")
fig.savefig("demo.svg")
plt.colse(fig)

将svg图片转换为png,jpg图片

# !pip install cairosvg==2.7.1 
import cairosvg
from PIL import Image
cairosvg.svg2png(url="demo.svg", write_to="svg2jpg.jpg", dpi=600)
img = Image.open("svg2jpg.jpg")
img

参考文档

  1. matplotlib.org/stable/user…

z先生说

今天给大家分享,