使用pyplot需要导入如下lib:
import matplotlib import matplotlib.pyplot as plt import matplotlib.gridspec as gs from matplotlib.backends.backend_pdf import PdfPages
1. 进行输出Page的配置
matplotlib.rcdefaults()
p = matplotlib.rcParams
# 配置图表字体 p["font.family"] = "sans-serif" p["font.sans-serif"] = ["SimHei", "Tahoma"] p["font.size"] = 10 p["axes.unicode_minus"] = False# 配置图表大小p["figure.figsize"] = (14.15, 20) # A4纸大小,竖向页面2. 生成PDF文件# p["figure.figsize"] = (20, 14.15) # A4纸大小,横向页面
# 配置图表分辨率p["figure.dpi"] = 200# 配置绘图区域的大小和位置,下面的值是基于图标的宽和高的比例 p["figure.subplot.left"] = 0.06 # 左边距 p["figure.subplot.right"] = 0.94 # 右边距 p["figure.subplot.bottom"] = 0.05 # 下边距 p["figure.subplot.top"] = 0.92 # 上边距# 配置subplots之间的间距(水平间距和垂直间距),也是基于图标的宽和高的比例p["figure.subplot.wspace"] = 0.12p["figure.subplot.hspace"] = 0.2
# 准备数据
import numpy as np
t = np.arange(0.0, 5.0, 0.01) data = np.cos(2*np.pi*t)
# 配置图形
pdf = PdfPages(pdf_file) # pdf_file为全路径的文件名
figure = plt.figure()figure.subplots_adjust(hspace=0.4) # 调整subplots之间的垂直方向的间距figure.suptitle("Title") # 设置页面上的标题
# 绘制第一个图形(曲线)
sp1 = figure.add_subplot(2, 1, 1) # 设置plot的布局(rows, cols, num)# rows: 一页中图形的行数# cols: 一页中图形的列数# num: 绘制第几个图形(从1开始)
# 还有一种写法: sp = figure.add_subplot(221)# 进行基本的图形绘制
n = len(data) # 要绘制数据的长度
sp1.set_xlim(0, n-1) # 设置x轴的范围sp1.set_ylim(-2, 2) # 设置y轴的范围,不设置的话会自动设置合适的y值范围(可视区域最大化)sp1.set_xlabel("x_label")
sp1.set_ylabel("y-label")
sp1.set_title("subtitle1", fontsize=10, color="b") # 设置当前图形的Titlesp1.plot(data, linewidth=0.5, color="b") # 以0.5线宽绘制蓝色的data图形# 绘制第二个图形(点)
sp2 = figure.add_subplot(212) sp2.set_xlabel("x_label_dot") sp2.set_ylabel("y-label_dot") sp2.set_title("subtitle2", fontsize=10, color="r") for x, y in enumerate(data): # 以尺寸为2绘制红色的点 sp2.plot(x, y, "o", markersize=2, markerfacecolor="red", markeredgecolor="red")
pdf.savefig(figure)输出图形如下:plt.close() pdf.close()
![]()
3. 如何将两个或多个图形合并在一起显示
使用GridSpec对象可以实现。
gs1 = gs.GridSpec(3, 1) # 网格设置为3行,1列,其中第一个图形占2行,第二个图形占1行 gs1.update(hspace=0, wspace=0, top=0.90, bottom=0.10) # 为使两个图形合并在一起,hspace和wspace必须设置为0,top/bottom是基于整个页面的比例 sp1 = plt.subplot(gs1[0:2, :]) # 注意gs中使用的是index(从0开始),不包含结束点。 # 第一个参数"0:2"表示从第1行开始,占用2行到第三行结束;第二个参数":"表示占用所有列 # 此处也可以使用 sp = figure.add_subplot(gs1[0:2, :])sp2 = plt.subplot(gs1[2:3, :]) # 从第二行开始,到第三行结束(不含第三行),占用一行# 此处也可以使用 sp = figure.add_subplot(gs1[2:3, :])
省略sp1和sp2的绘制过程,由于合并,不需显示sp1的xlabel和sp2的title,输出图形如下:
![]()
合并多个图形的示例(例如,合并5个图形在一起显示):
gs1 = gridspec.GridSpec(5, 1) # 网格设置为5行,每个图形占用一行sp1 = plt.subplot((gs[0, :])) # 每个图形占用一行,可以直接使用index表示sp2 = plt.subplot((gs[1, :]))sp3 = plt.subplot((gs[2, :]))sp4 = plt.subplot((gs[3, :]))sp5 = plt.subplot((gs[4, :]))4. X轴和Y轴的多个坐标系使用twinx()和twiny()方法。
twinx():共用X轴,使用新的Y轴坐标
twiny():共用Y轴,使用新的X轴坐标
创建新Y轴坐标:ax1 = sp1.twinx() # 第二Y轴(共用X轴) ax1.set_xlim(0, n-1) # 设置与sp1相同的X轴范围(不设置默认也是相同的X轴范围),如果修改则sp1的X轴范围也会同时改变 ymin, ymax = sp1.get_ylim() ax1.set_ylim(ymin-5, ymax+5) # Y轴与sp1的Y轴是独立开来的,可以随意设置而不影响sp1的Y轴范围 ax1.set_ylabel("第二Y轴:红色", color="r") for ytl in ax1.get_yticklabels(): # 设置为第二Y轴坐标显示为红色 ytl.set_color("r") ax1.set_xticks([]) # 此处设置为不显示X轴坐标,则整个图形就不显示X轴坐标了(共用sp1的X轴坐标),同时X轴的顶部和底部标尺都隐藏了 ax1.plot(data1, linewidth=0.5, color="r") # 绘制第二Y轴坐标系上的图形输出图形如下:
创建新X轴坐标:ax2 = sp1.twiny() # 第二X轴(共用Y轴) ax2.set_xlim(0, len(data1)-1) # X轴与sp1的X轴是独立开来的,可以随意设置而不影响sp1的X轴范围 ymin, ymax = sp1.get_ylim() ax2.set_ylim(ymin, ymax) # Y轴与sp1的Y轴是共用的,如果不设置则影响sp1的Y轴显示 ax2.set_xlabel("第二X轴:绿色", color="green") for xtl in ax2.get_xticklabels(): # 设置为第二X轴坐标显示为绿色 xtl.set_color("g") ax2.plot(data1, linewidth=0.5, color="g") # 绘制第二X轴坐标系上的图形 ax2.plot([0, n], [0, 0], linewidth=0.1, color="grey") # 绘制0基准线
输出图形如下:隐藏X轴顶部的标尺,但保留底部的标尺:# hide the top iden
ax2 = sp.twiny() ax2.set_xticks([])5. 自定义X轴和Y轴的坐标值sp = figure.add_subplot(111) sp.set_xlabel("x_label") sp.set_ylabel("y-label") sp.set_xticks(range(0, n, 20)) # 设置X轴的坐标点 sp.set_xticklabels(["%d" % val for val in range(0, n, 20)]) # 设置X轴的坐标显示标签 sp.set_ylim(-2, 2) sp.set_yticks([val/10 for val in range(-20, 21, 1)]) # 设置Y轴的坐标点 sp.set_yticklabels(["%.1f" % (val/10) for val in range(-20, 21, 1)]) # 设置Y轴的坐标显示标签 sp.plot([0, n], [0, 0], linewidth=0.1, color="grey") # 绘制0基准线 sp.plot(data, linewidth=0.5, color="b") # 以0.5线宽绘制蓝色的data图形输出图形如下:如果X轴的坐标label比较长,显示会叠加的话,可以指定角度显示坐标label,如下:
xticklabels = ["%d" % val for val in range(0, n, 20)]sp.set_xticklabels(xticklabels, rotation=40, fontsize=8, color="b") # 指定ticklabel旋转的角度
还可以设置是否显示网格:
sp.grid(True)输出图形如下:
6. 绘制柱状图
绘制柱状图可以直接使用line方式进行绘制,但会存在线条较粗时与底边无法对齐、或不同粗细的线条直接无法无缝衔接的问题。
sp = figure.add_subplot(111) sp.set_xlabel("x_label") sp.set_ylabel("y-label") sp.set_xlim(0, n-1) sp.set_ylim(-2, 2) sp.plot([0, n], [0, 0], linewidth=0.1, color="grey") # 绘制0基准线 sp.plot(data, linewidth=0.5, color="b") # 以0.5线宽绘制蓝色的data图形 # 绘制柱状图表 for i, val in enumerate(data): if i % 5 == 1: sp.plot([i, i], [0, val*3/5], linewidth=3, color="g")输出图形如下(每一根柱与0轴交汇的地方会突出来一些):
如上图,使用line方式绘制柱状图时会存在线条无法完美衔接的问题,此时使用bar绘制即可解决。
# 绘制柱状图表 left = [] height = [] width = [] bottom = [] color = [] for i, val in enumerate(data): if i % 5 == 1: left.append(i) height.append(val*3/5) width.append(3) bottom.append(0) color.append("r" if val > 0 else "g") sp.bar(left, height, width=width, bottom=bottom, edgecolor="none", color=color)输出图形如下:
绘制水平的柱图:
# 绘制水平的bars left = [] height = [] width = [] bottom = [] color = [] direction = 1 if data[0] > 0 else -1 bar_start = 0 for i, val in enumerate(data): if (val > 0 and direction != 1) or (val <= 0 and direction != -1): left.append(bar_start) bottom.append(0.5 if direction == 1 else -0.5) width.append(i - bar_start) height.append(0.05) color.append("r" if direction == 1 else "g") bar_start = i direction = 1 if val > 0 else -1 sp.bar(left, height, width=width, bottom=bottom, edgecolor="none", color=color)输出图形如下: