Python 3.x 如何连接两个matplotlib图形

Python 3.x 如何连接两个matplotlib图形,python-3.x,matplotlib,Python 3.x,Matplotlib,我有一个从数据生成matplotlib图形的脚本。这些绘图保存到磁盘,如下所示: fig,ax=plt.subplot() #创建绘图 # ... pickle.dump(ax,打开(属于“wb”)) 在另一个脚本中,我想加入其中的某些情节。我可以使用以下方法读取数据: figures=[pickle.load(file)for file in files] (FWIW,我读回的图形的类型为AxesSubplot) 到目前为止还不错。现在我想把两个(或更多)数字的数据放在一起,使用可用图的最大

我有一个从数据生成matplotlib图形的脚本。这些绘图保存到磁盘,如下所示:

fig,ax=plt.subplot()
#创建绘图
# ...
pickle.dump(ax,打开(属于“wb”))

在另一个脚本中,我想加入其中的某些情节。我可以使用以下方法读取数据:

figures=[pickle.load(file)for file in files]

(FWIW,我读回的图形的类型为
AxesSubplot

到目前为止还不错。现在我想把两个(或更多)数字的数据放在一起,使用可用图的最大或最小比例。由于我缺乏经验,我完全不知道如何做到这一点。我确实发现了关于连接图的问题,一致的意见是首先在一个图形中绘制。在我的例子中,这将是相当困难的,因为单个数据集的绘图逻辑已经很复杂。(为什么每个数据集在第一步中都应该单独绘制,然后才可能与其他数据集连接,还有其他原因)

我想要连接的图以相同的方式表示它们的数据,即所有的图都是直线图或直方图(不确定如何有意义地连接这些图)或QQplot(参见statsmodels.api)。它们的数据大小可能相同,也可能不同


如何连接不同图形中的绘图?

我想您会发现将数据保存到文件中更容易,以后可以从中生成新的绘图。您甚至可以使用将数据、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()


在上面,我使用
np.savez
np.load
而不是
pickle
来保存和恢复数据。或者,您可以对包含数据、方法及其参数的dict、tuple或list进行pickle。但是,由于数据主要是数字,因此使用
np.savez
创建函数以绘制特定轴 您通常会将打印放入一个函数中,该函数将要打印的轴作为参数。然后,您可以随时重用此函数

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()

让艺术家走向新形象 要回答这个问题,您可以将艺术家从未勾选的人物中移开,但这涉及到一些黑客行为,可能会导致不完美的结果:

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()
在这里,我们循环遍历未勾选图形中的所有线条和面片,将它们从旧图形中删除并添加到新图形中。为此,我们需要设置轴、变换和图形以正确匹配新图形。
这当然会变得越来越复杂,因为图形中的艺术家种类越来越多,需要的艺术家也越来越多。

克隆轴是不可能的。但是,可以将一个轴从一个酸洗图形移动到另一个图形,如图所示。但是这个问题也不要求,而是要求艺术家在坐标轴内移动。直到“data”的单数是“datum”@unutbu是正确的,这是因为我忽略了在迭代列表时从不操纵列表的基本原则。;-)我纠正了这一点。我发布了一个关于移动收藏的后续问题。@unutbu我在写“…如果这些艺术家有与他们相关的数据转换以外的转换,则需要更复杂的方法”:-@ImportanceOfBeingErnest非常感谢您的回答!这对我来说几乎是完美的——最后一个问题:我如何改变情节的颜色?我希望每个单独的情节都有自己的颜色,以便区分。我试着为每个艺术家设置颜色,但没有成功。
artist.set\u color