【问题标题】:matplotlib: combine different figures and put them in a single subplot sharing a common legendmatplotlib:组合不同的图形并将它们放在一个共享一个共同图例的子图中
【发布时间】:2013-05-20 20:35:51
【问题描述】:

我们有一个代码creates figures from input.txt files。我们需要将其中 2 个数字组合在一个子图中。图 1 中的数据将绘制在左侧子图中,图 2 中的数据将绘制在右侧子图中,共享相同的图例,并且在 x 轴和 y 轴上具有相同的比例:

这里有一些示例数据:

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

编辑:@nordev 建议的方法有效。现在将 ax1 和 ax2 对象传递给新图形会非常方便,因为它们有更多信息。 It seems that there is no straightforward way to achieve that

real case has been made available here。要使其工作,请运行plot_both.py


EDIT2:更改读取 input.txt 文件的例程更容易。 Now it supports multiple plots。但是这个问题仍然有效,因为将AxesSubplot 视为不同图形、子图等之间易于互换的对象会很棒......

【问题讨论】:

  • 要明确一点:您不能使用sharey 选项将这些数据简单地绘制为一个图中的两个子图吗?您必须创建两个单独的图形,然后提取图形并将它们组合成一个新图形?
  • 我尝试了 sharey 选项,但它似乎只共享the axis limits and views,而不是数据本身......并且当前代码创建了这些单独的数字,我想在更改之前尝试组合它们代码...
  • 我还是不完全明白你想要达到什么目的。在您包含的示例图中(图像 #1),y 轴是共享的,并且每个图中的数据仅绘制在一个子图中,即图是独立的。从您上面的评论来看,您似乎希望在 both 子图中绘制 both 行?例如,如果您希望第 1 行仅在子图 1 中绘制,而第 2 行仅在子图 2 中绘制,其中 y 轴具有相同的限制(共享 y 轴),这很容易。另外,您不能简单地使用与ax1.plot(... 中相同的参数调用plot 方法吗?
  • 我编辑了问题,请检查现在是否清楚...
  • 除了基本上按照我在下面建议的操作之外,您是否找到了解决原始问题的任何方法(将绘图作为同一图形的子图,而不是两个单独图形的子图)?

标签: python matplotlib


【解决方案1】:

这能解决您的问题吗?

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 实例作为子图(给出所需的布局),然后 then 绘图,而不是比绘图,然后提取/移动轴,因为你的问题最初是关于的。

正如我所怀疑的,最简单和最简单的解决方案是制作同一图形的各个 Axes 子图,而不是将它们绑定到单独的图形,因为将一个 Axes 实例从一个 Figure 移动到另一个是如评论中所述,不容易完成(如果可能的话)。 “原始”问题似乎仍然很难完成,因为只需将 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 参数应该被定制以适应我们的图形边界。

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

【讨论】:

  • 非常感谢!它有效,现在我正在尝试将AxesSubplot 对象传递给新图形,以更有效地从 fig1 和 fig2 获取所有信息......
  • @SaulloCastro 根据 Joe Kington 的this comment(2012 年 12 月),Axes 实例故意不应该在人物之间共享,这使得您的请求很难完成。
  • 我用真实案例的链接更新了问题,以防万一你想玩它......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-18
  • 2014-10-06
  • 1970-01-01
  • 2018-09-24
  • 1970-01-01
  • 2020-06-30
  • 1970-01-01
相关资源
最近更新 更多