2. 科研绘图之 matplotlib 图形窗口
matplotlib 图形窗口
图形对象(图形窗口)
- 子图;
- 刻度定位器;
- 刻度网格线;
- 半对数坐标;
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()
函数用于保存绘制的图像,参数如下:
filename
:保存图片文件的名称或路径,必选;figsize
:保存输出图像的大小,单位是英寸,比如:figsize=[8, 8]
;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()