Max*_*rch 2 matplotlib python-3.x
我有一个脚本,可从数据生成matplotlib数字。这些图将保存到磁盘,如下所示:
fig, ax = plt.subplots()
# create the plot
# ...
pickle.dump(ax, open(of, 'wb'))
在另一个脚本中,我想加入其中某些情节。我可以使用以下方式读取数据:
figures = [pickle.load(file) for file in files]
(FWIW,我读回的数字带有类型AxesSubplot。)
到目前为止,一切都很好。现在,我想使用可用图的最大或最小比例将两个(或多个)图形的数据放在一起。由于缺乏经验,我完全不知道如何实现这一目标。我确实发现了有关加入地块的问题,并且共识是首先绘制一个图形。在我的情况下,这将非常困难,因为单个数据集的绘制逻辑已经很复杂。(还有其他原因,为什么每个数据集都应首先自己绘制,然后才可能与其他数据集连接)。
我要加入的图以相同的方式表示其数据-即所有图都是线图或直方图(不确定要如何有效地连接那些图)或QQPlot(请参阅statsmodels.api)。它们可能具有或可能不具有相同的数据大小。
如何加入不同数字的地块?
您通常会将绘图放入一个函数中,该函数将要绘制的轴作为参数。然后,您可以随心所欲地重用此功能。
import numpy as np
import matplotlib.pyplot as plt
def myplot1(data, ax=None, show=False):
if not ax:
_, ax = plt.subplots()
ax.plot(data[0], data[1])
if show:
plt.show()
def myplot2(data, ax=None, show=False):
if not ax:
_, ax = plt.subplots()
ax.hist(data, bins=20, density=True)
if show:
plt.show()
x = np.linspace(-3, 3, 100)
y = np.exp(-x**2/2)/np.sqrt(2*np.pi)
a = np.random.normal(size=10000)
# create figure 1
myplot1((x,y))
#create figure 2
myplot2(a)
# create figure with both
fig, ax = plt.subplots()
myplot1((x,y), ax=ax)
myplot2(a, ax=ax)
plt.show()
Run Code Online (Sandbox Code Playgroud)
要回答这个问题,是的,您可以从未腌制的图形中移动艺术家,但这涉及一些黑客行为,可能会导致不完美的结果:
import matplotlib.pyplot as plt
import numpy as np
import pickle
x = np.linspace(-3, 3, 100)
y = np.exp(-x**2/2)/np.sqrt(2*np.pi)
a = np.random.normal(size=10000)
fig, ax = plt.subplots()
ax.plot(x, y)
pickle.dump(fig, open("figA.pickle","wb"))
#plt.show()
fig, ax = plt.subplots()
ax.hist(a, bins=20, density=True, ec="k")
pickle.dump(fig, open("figB.pickle","wb"))
#plt.show()
plt.close("all")
#### No unpickle the figures and create a new figure
# then add artists to this new figure
figA = pickle.load(open("figA.pickle","rb"))
figB = pickle.load(open("figB.pickle","rb"))
fig, ax = plt.subplots()
for figO in [figA,figB]:
lists = [figO.axes[0].lines, figO.axes[0].patches]
addfunc = [ax.add_line, ax.add_patch]
for lis, func in zip(lists,addfunc):
for artist in lis[:]:
artist.remove()
artist.axes=ax
artist.set_transform(ax.transData)
artist.figure=fig
func(artist)
ax.relim()
ax.autoscale_view()
plt.close(figA)
plt.close(figB)
plt.show()
Run Code Online (Sandbox Code Playgroud)
在这里,我们遍历未腌制图形中的所有线条和补丁,将它们从旧图形中删除并将它们添加到新图形中。为此,我们需要设置轴、变换和图形以正确匹配新图形。这当然会变得越来越复杂,因为图中的艺术家种类越多,如果这些艺术家有与他们关联的数据变换以外的变换,则需要更复杂的方法。
我认为您会发现将数据保存到文件中更容易,以后可以从该文件中生成新图。您甚至可以使用np.savez它不仅将数据保存,还将plot方法及其参数保存在一个文件中。这是您以后如何加载这些文件以在新图中生成“连接”图的方式:
import matplotlib.pyplot as plt
import numpy as np
def join(ax, files):
data = [np.load(filename) for filename in files]
for datum in data:
method = getattr(ax, datum['method'].item())
args = tuple(datum['args'])
kwargs = datum['kwargs'].item()
method(*args, **kwargs)
x = np.linspace(-3, 3, 100)
y = np.exp(-x**2/2)/np.sqrt(2*np.pi)
a = np.random.normal(size=10000)
fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()
np.savez('/tmp/a.npz', method='plot', args=(x, y), kwargs=dict())
fig, ax = plt.subplots()
ax.hist(a, bins=100, density=True)
plt.show()
np.savez('/tmp/b.npz', method='hist', args=(a,),
kwargs=dict(bins=100, density=True))
fig, ax = plt.subplots()
join(ax, ['/tmp/a.npz', '/tmp/b.npz'])
plt.show()
Run Code Online (Sandbox Code Playgroud)
上面我使用np.savez而np.load不是pickle保存和还原数据。或者,您可以腌制包含数据,方法及其参数的字典,元组或列表。但是,由于数据主要是数字数据,np.savez因此与pickle相比,使用效率更高,并且安全风险较小。