如何加入两个matplotlib数字

时间:2018-02-21 17:58:39

标签: python-3.x matplotlib

我有一个脚本,可以根据数据生成matplotlib数据。这些图按如下方式保存到磁盘:

fig, ax = plt.subplots() # create the plot # ... pickle.dump(ax, open(of, 'wb'))

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

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

(FWIW,我读回的数据的类型为AxesSubplot。)

到目前为止一切顺利。现在我想使用可用图的最大或最小比例将两个(或更多)数字的数据放在一起。由于我缺乏经验,我完全不知道如何实现这一目标。我确实找到了关于加入情节的问题,并且共识是首先在一个图中绘制。在我的情况下,由于单个数据集的绘图逻辑已经非常复杂,因此相当困难。 (还有其他原因可以解释为什么每个数据集应该在第一步中独立绘制,然后才可能与其他数据集联合起来。)

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

如何加入不同数字的情节?

2 个答案:

答案 0 :(得分:3)

我认为您会发现将数据保存到以后可以生成新图表的文件更容易。你甚至可以使用np.savez不仅保存数据,还将plot方法及其参数保存在一个文件中。以下是您以后load这些文件在新图中生成“已加入”图的方法:

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

enter image description here

上面我使用np.saveznp.load代替pickle来保存和恢复数据。或者,您可以选择包含数据,方法及其参数的字典,元组或列表。但是,由于数据主要是数字,因此np.savez使用more efficient and less of a security risk than pickle

答案 1 :(得分:3)

创建绘制到特定轴的函数

您通常会将绘图放入一个函数中,该函数将轴绘制为参数。然后,您可以随意重复使用此功能。

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

在这里,我们循环遍历未打印的图形中的所有线条和补丁,将它们从旧图形中移除并将它们添加到新图形中。为此,我们需要设置轴,变换和图形以正确匹配新图形。 这当然会越来越复杂,图中有更多不同类型的艺术家,需要even more complex methods if those artists have transforms other than the data transform associated with them