Python matplotlib:在多个页面中保存为 pdf
Python matplotlib: Save to pdf in multiple pages
我正在尝试执行以下操作:
我使用 matplotlib 创建了一个图形,其中包含几个子图。
更具体地说,2x4 子图
输出非常适合在屏幕上显示,但不适合保存为 pdf。
如果我只使用 save_fig
,它会打印一个单页 pdf 文档,网格为 2x4。
我想做的是重新安排我的子图,比方说一个 2x4 网格(选择哪个子图去哪里,会很好,但不是必需的)并将其打印为 2 页 pdf每个 4 个子图。 (为了能够适应A4页面大小)
这可能吗?
在此先感谢您!
我建议创建 3 个数字。一个用于显示,两个用于保存和绘制相同的数据。
import matplotlib.pyplot as plt
import numpy as np
data = np.sort(np.cumsum(np.random.rand(24,16), axis=0), axis=0)
def plot(ax, x, y, **kwargs):
ax.plot(x,y, **kwargs)
colors = ["crimson", "indigo", "limegreen", "gold"]
markers = ["o", "", "s", ""]
lines = ["", "-", "", ":"]
# figure 0 for showing
fig0, axes = plt.subplots(nrows=2,ncols=4)
for i, ax in enumerate(axes.flatten()):
plot(ax, data[:,2*i], data[:,2*i+1], marker=markers[i%4], ls=lines[i%4],color=colors[i%4])
# figure 1 for saving
fig1, axes = plt.subplots(nrows=1,ncols=4)
for i, ax in enumerate(axes.flatten()):
plot(ax, data[:,2*i], data[:,2*i+1], marker=markers[i], ls=lines[i],color=colors[i])
#figure 2 for saving
fig2, axes = plt.subplots(nrows=1,ncols=4)
for i, ax in enumerate(axes.flatten()):
plot(ax, data[:,2*i+4], data[:,2*i+1+4], marker=markers[i], ls=lines[i],color=colors[i])
#save figures 1 and 2
fig1.savefig(__file__+"1.pdf")
fig2.savefig(__file__+"2.pdf")
#close figures 1 and 2
plt.close(fig1)
plt.close(fig2)
#only show figure 0
plt.show()
因为我的工作需要类似的东西,所以我努力根据显示媒体将图表分组的过程自动化。起初我的想法是每个图只做一次,然后将子图添加到要保存在 pdf 中的图形中,但遗憾的是,根据 this answer 中的评论,这是不可能的,所以一切都需要重新绘制。该代码显示了如何使用 PdfPages
:
实现自动化的一般思路
from matplotlib import pyplot as plt
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
def niter(iterable, n):
"""
Function that returns an n-element iterator, i.e.
sub-lists of a list that are max. n elements long.
"""
pos = 0
while pos < len(iterable):
yield iterable[pos:pos+n]
pos += n
def plot_funcs(x, functions, funcnames, max_col, max_row):
"""
Function that plots all given functions over the given x-range,
max_col*max_row at a time, creating all needed figures while doing
so.
"""
##amount of functions to put in one plot
N = max_col*max_row
##created figures go here
figs = []
##plotted-on axes go here
used_axes = []
##looping through functions N at a time:
for funcs, names in zip(niter(functions, N), niter(funcnames,N)):
##figure and subplots
fig, axes = plt.subplots(max_col, max_row)
##plotting functions
for name,func,ax in zip(names, funcs, axes.reshape(-1)):
ax.plot(x, func(x))
ax.set_title(name)
used_axes.append(ax)
##removing empty axes:
for ax in axes.reshape(-1):
if ax not in used_axes:
ax.remove()
fig.tight_layout()
figs.append(fig)
return figs
##some functions to display
functions = [
lambda x: x, lambda x: 1-x, lambda x: x*x, lambda x: 1/x, #4
np.exp, np.sqrt, np.log, np.sin, np.cos, #5
]
funcnames = ['x','1-x', 'x$^2$', '1/x', 'exp', 'sqrt', 'log', 'sin','cos']
##layout for display on the screen
disp_max_col = 3
disp_max_row = 2
##layout for pdf
pdf_max_col = 2
pdf_max_row = 4
##displaying on the screen:
x = np.linspace(0,1,100)
figs = plot_funcs(x, functions, funcnames, disp_max_row, disp_max_col)
plt.show()
##saving to pdf if user wants to:
answer = input('Do you want to save the figures to pdf?')
if answer in ('y', 'Y', 'yes', ''):
##change number of subplots
N = disp_max_col*disp_max_row
figs = plot_funcs(x, functions, funcnames, pdf_max_row, pdf_max_col)
##from https://matplotlib.org/examples/pylab_examples/multipage_pdf.html
with PdfPages('multipage_pdf.pdf') as pdf:
for fig in figs:
plt.figure(fig.number)
pdf.savefig()
核心功能,plot_funcs
采用 max_col
和 max_row
关键字,然后使用相应数量的子图创建图形。然后循环遍历给定的要绘制的函数列表,每个函数都在其自己的子图中。未使用的子图被删除。最后返回所有图形的列表。
在我的示例中,我有 9 个不同的函数,我首先以 2x3 布局在屏幕上显示它们(总共制作两个图形,一个有 6 个子图,一个有 3 个子图)。如果用户满意,这些图将以 2x4 布局重做(同样是两个图,但这次一个有 8 个子图,一个有 1 个子图),然后保存到一个名为 multipage_pdf.pdf
的文件中,在 [=17] 之后=].
在 python 3.5
上测试
我正在尝试执行以下操作:
我使用 matplotlib 创建了一个图形,其中包含几个子图。 更具体地说,2x4 子图
输出非常适合在屏幕上显示,但不适合保存为 pdf。
如果我只使用 save_fig
,它会打印一个单页 pdf 文档,网格为 2x4。
我想做的是重新安排我的子图,比方说一个 2x4 网格(选择哪个子图去哪里,会很好,但不是必需的)并将其打印为 2 页 pdf每个 4 个子图。 (为了能够适应A4页面大小)
这可能吗?
在此先感谢您!
我建议创建 3 个数字。一个用于显示,两个用于保存和绘制相同的数据。
import matplotlib.pyplot as plt
import numpy as np
data = np.sort(np.cumsum(np.random.rand(24,16), axis=0), axis=0)
def plot(ax, x, y, **kwargs):
ax.plot(x,y, **kwargs)
colors = ["crimson", "indigo", "limegreen", "gold"]
markers = ["o", "", "s", ""]
lines = ["", "-", "", ":"]
# figure 0 for showing
fig0, axes = plt.subplots(nrows=2,ncols=4)
for i, ax in enumerate(axes.flatten()):
plot(ax, data[:,2*i], data[:,2*i+1], marker=markers[i%4], ls=lines[i%4],color=colors[i%4])
# figure 1 for saving
fig1, axes = plt.subplots(nrows=1,ncols=4)
for i, ax in enumerate(axes.flatten()):
plot(ax, data[:,2*i], data[:,2*i+1], marker=markers[i], ls=lines[i],color=colors[i])
#figure 2 for saving
fig2, axes = plt.subplots(nrows=1,ncols=4)
for i, ax in enumerate(axes.flatten()):
plot(ax, data[:,2*i+4], data[:,2*i+1+4], marker=markers[i], ls=lines[i],color=colors[i])
#save figures 1 and 2
fig1.savefig(__file__+"1.pdf")
fig2.savefig(__file__+"2.pdf")
#close figures 1 and 2
plt.close(fig1)
plt.close(fig2)
#only show figure 0
plt.show()
因为我的工作需要类似的东西,所以我努力根据显示媒体将图表分组的过程自动化。起初我的想法是每个图只做一次,然后将子图添加到要保存在 pdf 中的图形中,但遗憾的是,根据 this answer 中的评论,这是不可能的,所以一切都需要重新绘制。该代码显示了如何使用 PdfPages
:
from matplotlib import pyplot as plt
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
def niter(iterable, n):
"""
Function that returns an n-element iterator, i.e.
sub-lists of a list that are max. n elements long.
"""
pos = 0
while pos < len(iterable):
yield iterable[pos:pos+n]
pos += n
def plot_funcs(x, functions, funcnames, max_col, max_row):
"""
Function that plots all given functions over the given x-range,
max_col*max_row at a time, creating all needed figures while doing
so.
"""
##amount of functions to put in one plot
N = max_col*max_row
##created figures go here
figs = []
##plotted-on axes go here
used_axes = []
##looping through functions N at a time:
for funcs, names in zip(niter(functions, N), niter(funcnames,N)):
##figure and subplots
fig, axes = plt.subplots(max_col, max_row)
##plotting functions
for name,func,ax in zip(names, funcs, axes.reshape(-1)):
ax.plot(x, func(x))
ax.set_title(name)
used_axes.append(ax)
##removing empty axes:
for ax in axes.reshape(-1):
if ax not in used_axes:
ax.remove()
fig.tight_layout()
figs.append(fig)
return figs
##some functions to display
functions = [
lambda x: x, lambda x: 1-x, lambda x: x*x, lambda x: 1/x, #4
np.exp, np.sqrt, np.log, np.sin, np.cos, #5
]
funcnames = ['x','1-x', 'x$^2$', '1/x', 'exp', 'sqrt', 'log', 'sin','cos']
##layout for display on the screen
disp_max_col = 3
disp_max_row = 2
##layout for pdf
pdf_max_col = 2
pdf_max_row = 4
##displaying on the screen:
x = np.linspace(0,1,100)
figs = plot_funcs(x, functions, funcnames, disp_max_row, disp_max_col)
plt.show()
##saving to pdf if user wants to:
answer = input('Do you want to save the figures to pdf?')
if answer in ('y', 'Y', 'yes', ''):
##change number of subplots
N = disp_max_col*disp_max_row
figs = plot_funcs(x, functions, funcnames, pdf_max_row, pdf_max_col)
##from https://matplotlib.org/examples/pylab_examples/multipage_pdf.html
with PdfPages('multipage_pdf.pdf') as pdf:
for fig in figs:
plt.figure(fig.number)
pdf.savefig()
核心功能,plot_funcs
采用 max_col
和 max_row
关键字,然后使用相应数量的子图创建图形。然后循环遍历给定的要绘制的函数列表,每个函数都在其自己的子图中。未使用的子图被删除。最后返回所有图形的列表。
在我的示例中,我有 9 个不同的函数,我首先以 2x3 布局在屏幕上显示它们(总共制作两个图形,一个有 6 个子图,一个有 3 个子图)。如果用户满意,这些图将以 2x4 布局重做(同样是两个图,但这次一个有 8 个子图,一个有 1 个子图),然后保存到一个名为 multipage_pdf.pdf
的文件中,在 [=17] 之后=].
在 python 3.5
上测试