2. 科研绘图之 matplotlib 图形窗口

matplotlib 图形窗口

图形对象(图形窗口)

  1. 子图;
  2. 刻度定位器;
  3. 刻度网格线;
  4. 半对数坐标;

1、图形对象(图形窗口)

matplotlib 创建窗口的API

# 手动创建 matplotlib 窗口
plt.figure(
    title='title',   # 窗口标题栏文本
    figsize=(4, 3),  # 窗口大小(元组)
    dpi=120,         # 像素密度
    facecolor=''     # 图表背景色
)
plt.show()

plt.figure 方法可以构建一个新窗口,如果已经构建过 title='AAA' 的窗口的话,plt 将不会创建新的窗口,而是把 title='AAA' 的窗口置为当前操作的窗口。

import matplotlib.pyplot as plt

plt.figure('A figure',facecolor='gray')  
# facecolor设置窗口或画板为灰度的
plt.plot([0,1],[1,2])
plt.figure('B figure',facecolor='lightgray')
# facecolor设置窗口或画板为浅灰色
plt.plot([1,2],[2,1])
# 如果figure中标题已创建,则不会新建窗口
# 而是将旧窗口(相同窗口标题的)置为当前窗口
plt.figure('A figure',facecolor='gray')
# 后续的操作也是针对'A figure'执行的
plt.plot([1,2],[2,1])
plt.show()

在这里插入图片描述

从显示的绘图结果可以看出,A figure 窗口中又增加了以 (1, 2)、(2, 1) 为端点的直线。

2、设置当前窗口的参数

从上面绘制的图像,我们发现它缺失标题说明、坐标轴的刻度值偏小而不清晰、没有必要的坐标轴文本标注,所以接着介绍下面几种方法:

  • 图表的标题:plt.title()

  • 坐标轴文本:plt.xlabel()plt.ylabel()

  • 刻度线参数:plt.tick_params

  • 图表网格线:plt.grid()

# 设置图表标题,标题显示在图表上方
plt.title(title, fontsize=12)
# 设置水平轴的文本
plt.xlabel(x_label_str, fontsize=12)
# 设置垂直轴的文本
plt.ylabel(y_label_str, fontsize=12)
# 设置刻度参数,labelsize设置刻度字体大小
plt.tick_params(labelsize=8)
# 设置图表网格线  linestyle设置网格线的样式
"""
1. -  or solid     粗线
2. -- or dashed    虚线
3. -. or dashdot   点虚线
4. :  or dotted    点线
"""
plt.grid(linestyle='')
# 设置紧凑布局,把图表相关参数都显示在窗口中
plt.tight_layout() 

案例:以正弦函数 y = s i n x y=sinx y=sinx 为例,测试窗口相关参数;

import matplotlib.pyplot as plt
import numpy as np

# 创建一个新窗口,标题为sinx figure
plt.figure('Sinx figure')
xdata = np.linspace(-2 * np.pi, 2 * np.pi, 100)
ydata = np.sin(xdata)
plt.plot(xdata, ydata, linewidth=2, alpha=0.9, color='dodgerblue')
plt.title(r'$y=sin(x)$', fontsize=18)
plt.xlabel('time', fontsize=16)
plt.ylabel('price', fontsize=16)
plt.grid(linestyle=':')
plt.tick_params(labelsize=14)
plt.tight_layout()
plt.savefig('sinx3.jpg')
plt.show()

在这里插入图片描述

如果需要在 matplotlib 绘制的图像中显示中文字体怎么该怎么办呢?

在 matplotlib 绘图函数中默认是不支持中文字体的显示的,所以需要自己手动设置。

  • 全局字体设置
import matplotlib.pyplot as plt

# 全局字体设置
## 步骤一:替换默认的 sans-serif 字体
plt.rcParams['font.sans-serif'] = ['KaiTi']
## 步骤二:解决坐标轴负数的负号显示问题
plt.rcParams['axes.unicode_minus'] = False

xdata = np.linspace(0, 100, 1000)
ydata = -(xdata - 50) ** 2 + 5050
plt.plot(xdata, ydata, linewidth=2, alpha=0.9, color='dodgerblue')

plt.title("速度与车流量之间的关系",fontsize=16)
plt.xlabel("x轴",fontsize=16)
plt.ylabel("y轴",fontsize=16)
plt.savefig('fig2.png')
plt.show()

在这里插入图片描述

  • 局部字体设置
import matplotlib.pyplot as plt

# 局部字体设置,标题和坐标轴的字体可以分开设置
plt.xlabel("x轴", fontproperties="SimSun")
plt.ylabel('y轴', fontproperties="SimSun")
plt.title("标题", fontproperties="SimHei")
plt.show()

一些常用的中文字体英文名(当然也可以使用本机系统的字体样式):

中文字体英文名中文字体英文名
宋体SimSun华文楷体STKaiti
黑体SimHei华文宋体STSong
微软雅黑Microsoft YaHei华文仿宋STFangsong
楷体KaiTi微软正黑体Microsoft JhengHei
仿宋FangSong细明体MingLiU

3、子图布局

绘制矩阵式布局相关的API(常用):plt.subplot(rows, cols, num),其中 rows 表示行数,cols 表示列数,num 表示子图的编号。

# 图表背景色设为亮灰色
plt.figure('subplot Layout', facecolor='lightgray')
"""
plt.subplot(rows, cols, num)
rows:行数
cols:列数
num:编号
"""
# 操作3行3列的矩阵中编号为5的子图
plt.subplot(3, 3, 5)
# 1 2 3
# 4 5 6
# 7 8 9
plt.subplot(335)  # 简写

案例:绘制九宫格矩阵式子图,每个子图中写一个数字。

import numpy as np
import matplotlib.pyplot as plt

# 创建一个窗口
plt.figure('subplot', facecolor='lightgray')
for i in range(1, 10):
    plt.subplot(3, 3, i)  # 选择子图
    plt.text(0.5, 0.5, str(i), ha='center', va='center',size=36,alpha=0.6)
    plt.xticks([])
    plt.yticks([])
    plt.tight_layout()
plt.show()

通过 figure.add_aubplot() 绘制子图

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 创建一个画布或窗口
fig = plt.figure(figsize=(10, 8))

# 子图1
x = np.linspace(1, 10,100)
ax1 = fig.add_subplot(221)
ax1.plot(x, x ** 2)

# 子图2
ax2 = fig.add_subplot(222)
ax2.scatter(x, np.random.rand(100), s=10)
ax2.set_xlim(0, 12)
ax2.set_ylim(0, 1.2)
ax2.spines['top'].set_color('none')  # 表示不显示top坐标轴
ax2.spines['right'].set_color('none')

# 子图3
ax3 = fig.add_subplot(223)
ax3.plot(x, np.log(x))
# 如何给其中的子图添加坐标轴标注和标题
# 通过ax3操作子图的窗口参数
ax3.set_title(r"$y=log(x)$")
ax3.set_xlabel("time")
ax3.set_ylabel("price")
ax3.legend()

# 子图4
ax4 = fig.add_subplot(224)
ax4.plot(x, np.sin(x))
plt.show()

通过 plt.subplots() 绘制子图,subplots() 返回的值的类型为元组,其中包含了两个元素:第一个为一个画布或窗口,第二个是子图的列表;

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

fig, axes = plt.subplots(2, 2)

# 折线图
x1 = np.arange(1, 100)
y1 = x1 ** 2
axes[0][0].plot(x1, x1 ** 2)

# 散点图
x2 = np.arange(0, 10)
y2 = np.random.rand(10)
axes[0][1].scatter(x2, y2)

# 饼图
x3 = [15,30,45,10]  # 累加和为100
axes[1][0].pie(x3, labels=list('ABCD'), autopct='%.0f', explode=[0,0.05,0,0])

# 条形图
x4 = ['A', 'B', 'C', 'D', 'E']
y4 = [25, 15, 35, 30, 20]
axes[1][1].bar(x4, y4, color='b')
plt.show()

4、保存绘制的图像

matplotlib 支持的图片存储格式:eps, jpeg, jpg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff。

plt.savefig() 函数用于保存绘制的图像,参数如下:

  1. filename:保存图片文件的名称或路径,必选;
  2. figsize:保存输出图像的大小,单位是英寸,比如:figsize=[8, 8]
  3. dpi:图像保存的分辨率(分辨率越高,图像越清晰),单位为像素,一般设置为 dpi=600
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-np.pi, np.pi, 1000)
sinx = np.sin(x)
cosx = 1/2 * np.cos(x)

plt.plot(x, sinx, linestyle='-.', linewidth=2, color='dodgerblue', label=r'$y=sin(x)$')
plt.plot(x, cosx, linestyle='--', linewidth=2, color='orangered', label=r'$y=\frac{1}{2}cos(x)$')
plt.legend(loc='upper left')
# 图像不够清晰就调dpi分辨率的大小
plt.savefig('figC.jpg', figsize=[8, 8], dpi=600)
plt.show()

5、刻度定位器

刻度定位器相关的API:

# 获取当前坐标轴
ax = plt.gca()
# 设置水平坐标轴的主刻度定位器
ax.xaxis.set_major_locator(plt.NullLocator(1))
# 设置水平坐标轴的次刻度定位器为多点定位器,间隔0.1
ax.xaxis.set_minor_locator(plt.MultipleLocator(0,1))

案例:绘制一个数轴;

import matplotlib.pyplot as plt

plt.figure(figsize=(8, 6), dpi=100)
# 获取当前坐标轴
plt.xlim(0, 10)
ax = plt.gca()
# 隐藏除底轴以外的所有坐标轴
ax.spines['left'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
# 将底坐标轴调整到子图中心位置
ax.spines['bottom'].set_position(('data',0))
plt.yticks([])
# 设置水平坐标轴的主刻度的定位器
ax.xaxis.set_major_locator(plt.MultipleLocator(1))
# 设置水平坐标轴的次刻度器为多点定位器,间隔0.1
ax.xaxis.set_minor_locator(plt.MultipleLocator(0.2))
# 标记所用刻度定位器类名 
plt.text(5, 0.3,s='MultipleLocator', ha='center', size=14)
plt.show()

在这里插入图片描述

6、刻度网格线

绘制刻度网格线相关的API

ax = plt.gca()
# 绘制刻度网格线
ax.grid(
    which='',      # 设置主刻度/次刻度(major / minor),默认是major
    axis='',       # x / y / both,默认是both
    linewidth=1,   # 线宽
    linestyle=''   # 线型
    color='',      # 颜色,默认是灰
    alpha=0.5      # 透明度
)
import matplotlib.pyplot as plt
import numpy as np

plt.figure('Grid Line',figsize=(8, 6))
x = np.linspace(-2 * np.pi, 2 * np.pi, 100)
y = np.cos(x)
plt.plot(x, y, linestyle='--', color='dodgerblue',linewidth=1.5)
plt.title(r"$y=cos(x)$",fontsize=16)
plt.xlabel("x", fontsize=16)
plt.ylabel("y", fontsize=16)
plt.grid(linestyle=":")  # 使用默认参数major/both
plt.show()

在这里插入图片描述

综合案例:绘制曲线 [1, 10, 100, 1000, 100, 10, 1],然后设置刻度网格线,测试刻度网格线的参数。

import matplotlib.pyplot as plt

plt.figure('Grid Line',figsize=(8, 6))
ax = plt.gca()
# 修改x与y的刻度定位器
ax.xaxis.set_major_locator(plt.MultipleLocator(1))
ax.xaxis.set_minor_locator(plt.MultipleLocator(0.2))

ax.yaxis.set_major_locator(plt.MultipleLocator(250))
ax.yaxis.set_minor_locator(plt.MultipleLocator(50))
# 绘制网格线
ax.grid(which='major', axis='both',
       color='orangered',linewidth=0.5)
ax.grid(which='minor', axis='both',
       color='orangered',linewidth=0.1)
# 绘制曲线
y = [1, 10, 100, 1000, 100, 10, 1]
plt.plot(y, 'o-', color='dodgerblue',linewidth=0.75)
plt.savefig("fig1.png")
plt.show()

在这里插入图片描述

**半对数坐标:**y轴将以指数方式递增,即:plt.semilogy()

基于半对数坐标绘制第二个子图,表示曲线:[1, 10, 100, 1000, 100, 10, 1]。

import matplotlib.pyplot as plt

plt.figure('Grid Line',figsize=(8, 6))
ax = plt.gca()
# 修改x与y的刻度定位器
ax.xaxis.set_major_locator(plt.MultipleLocator(1))
ax.xaxis.set_minor_locator(plt.MultipleLocator(0.2))

ax.yaxis.set_major_locator(plt.MultipleLocator(250))
ax.yaxis.set_minor_locator(plt.MultipleLocator(50))
ax.grid(which='major', axis='both',
       color='orangered',linewidth=0.5)
ax.grid(which='minor', axis='both',
       color='orangered',linewidth=0.1)
# 绘制曲线
x = [1, 2, 3, 4, 5, 6, 7]
y = [1, 10, 100, 1000, 100, 10, 1]
plt.semilogy(x, y, 'o-', color='dodgerblue',linewidth=0.75)
plt.savefig("fig3.png")
plt.show()

在这里插入图片描述