21

We have a code that creates figures from input.txt files. We need to combine 2 of these figures in a single subplot. The data from figure1 will be plotted in the left subplot and from figure2 in the right subplot, sharing the same legend and witht he same scale in axes x and y:

enter image description here

Here there is some example data:

x  = [ 1, 2, 3, 5, 10, 100, 1000 ]
y1 = [ 1, 0.822, 0.763, 0.715, 0.680, 0.648, 0.645 ]
y2 = [ 1, 0.859, 0.812, 0.774, 0.746, 0.721, 0.718 ]

import matplotlib.pyplot as plt
# mode 01 from one case
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
ax1.plot( x, y1, label='mode 01' )
# mode 01 from other case
fig2 = plt.figure()
ax2 = fig2.add_subplot(111)
ax2.plot( x, y2, label='mode 01' )

EDIT: the method suggested by @nordev works. Now it would be really convenient to pass the ax1 and ax2 objects to the new figure, since they have much more information. It seems that there is no straightforward way to achieve that.

The real case has been made available here. To make it work, please run plot_both.py.


EDIT2: it was easier to change the routine that reads the input.txt files. Now it supports multiple plots. But the question is still valid because it would be great to treat the AxesSubplot as an easily interchangeable object among different figures, subplots and so forth...

4

1 回答 1

15

这能解决你的问题吗?

x  = [ 1, 2, 3, 5, 10, 100, 1000 ]
y1 = [ 1, 0.822, 0.763, 0.715, 0.680, 0.648, 0.645 ]
y2 = [ 1, 0.859, 0.812, 0.774, 0.746, 0.721, 0.718 ]

import matplotlib.pyplot as plt
from matplotlib.transforms import BlendedGenericTransform
# mode 01 from one case
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
line1, = ax1.plot( x, y1, label='mode 01' )
# mode 01 from other case
fig2 = plt.figure()
ax2 = fig2.add_subplot(111)
line2, = ax2.plot( x, y2, label='mode 01' )

# Create new figure and two subplots, sharing both axes
fig3, (ax3, ax4) = plt.subplots(1,2,sharey=True, sharex=True,figsize=(10,5))

# Plot data from fig1 and fig2
line3, = ax3.plot(line1.get_data()[0], line1.get_data()[1])
line4, = ax4.plot(line2.get_data()[0], line2.get_data()[1])
# If possible (easy access to plotting data) use
# ax3.plot(x, y1)
# ax4.lpot(x, y2)

ax3.set_ylabel('y-axis')
ax3.grid(True)
ax4.grid(True)

# Add legend
fig3.legend((line3, line4),
            ('label 3', 'label 4'),
            loc = 'upper center',
            bbox_to_anchor = [0.5, -0.05],
            bbox_transform = BlendedGenericTransform(fig3.transFigure, ax3.transAxes))
# Make space for the legend beneath the subplots
plt.subplots_adjust(bottom = 0.2)
# Show only fig3
fig3.show()

这给出了如下所示的输出 在此处输入图像描述

编辑

查看您上传的 zip 文件中的代码,我会说大部分请求的功能都已实现?

我看到您更改了创建绘图的函数,使您的问题的解决方案完全不同,因为您不再试图“合并”来自不同图形的两个子图。您的解决方案与我上面介绍的解决方案基本相同,因为两者都Axes在同一图形上创建两个实例作为子图(提供所需的布局),然后绘制,而不是绘制,然后提取/移动轴,因为你的问题最初是关于的。

正如我所怀疑的,最简单和最简单的解决方案是制作Axes同一图形的各个子图,而不是将它们绑定到单独的图形,因为将一个Axes实例从一个实例移到另一个实例Figure并不容易(如果可能的话),如指定的那样在评论中。“原始”问题似乎仍然很难完成,因为简单地向's添加一个Axes实例就很难自定义到所需的布局。Figure_axstack

ax.legend(...对当前代码的一项修改,使图例水平居中,顶部位于轴下方:

# Add this line
from matplotlib.transforms import BlendedGenericTransform

# Edit the function call to use the BlendedGenericTransform
ax.legend(loc='upper center',
          ncol=7,
          labelspacing=-0.7,
          columnspacing=0.75,
          fontsize=8,
          handlelength=2.6,
          markerscale=0.75,
          bbox_to_anchor=(0.5, -0.05),
          bbox_transform=BlendedGenericTransform(fig.transFigure, ax.transAxes))

在这里,bbox_to_anchor应该定制参数以适应我们图形的边界。

允许 x 轴和 y 轴的BlendedGenericTransform变换不同,这在许多情况下都非常有用。

于 2013-05-25T13:26:23.793 回答