matplotlib:组合不同的图形并将它们放在共享相同图例的单个子图中 [英] matplotlib: combine different figures and put them in a single subplot sharing a common legend

查看:1424
本文介绍了matplotlib:组合不同的图形并将它们放在共享相同图例的单个子图中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个代码

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:

这里有一些示例数据:

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对象传递给新图形真的很方便,因为它们具有更多信息. 似乎那里不是实现这一目标的直接方法.

真实案例已在此处提供.要使其正常运行,请运行plot_both.py.

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

更容易更改读取input.txt文件的例程. 现在它支持多个绘图.但是该问题仍然有效,因为将AxesSubplot作为不同图形,子图等之间易于互换的对象非常好.

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...

推荐答案

这是否解决了您的问题?

Does this solve your problem?

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

这给出了如下所示的输出

This gives output as seen below

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

Looking at the code in your uploaded zip-file, I'd say most of the requested functionality is achieved?

我看到您已经更改了创建绘图的功能,从而使您的问题的解决方案大为不同,因为您不再尝试合并"来自不同图形的两个子图.您的解决方案基本上与我上面介绍的解决方案相同,因为两者都在同一图形上创建了两个Axes实例作为子图(给出了所需的布局),并进行了 then 绘制,而不是绘图,然后提取/移动轴,因为您的问题本来就是

I see you have changed the function creating the plots, making the solution to your problem radically different, as you are no longer trying to "merge" two subplots from different figures. Your solution is basically the same as the one I presented above, in the sense that both are creating both Axes instances as subplots on the same figure (giving the desired layout), and then plotting, rather than plotting, then extract/move the axes, as your question was concerning originally.

最简单,最简单的解决方案是制作同一图形的各个Axes子图,而不是将它们绑定到单独的图形,因为将一个Axes实例从一个Figure移至另一个是如评论中所述,不容易完成(如果可能的话). 原始"问题似乎仍然很难解决,因为仅在Figure_axstack中添加Axes实例就很难自定义所需的布局.

As I suspected, the easiest and most trivial solution is to make the individual Axes subplots of the same figure instead of having them tied to separate figures, as moving one Axes instance from one Figure to another is not easily accomplished (if at all possible), as specified in a comment. The "original" problem still seems to be very hard to accomplish, as simply adding an Axes instance to the Figure's _axstack makes it hard to customize to the desired layout.

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

One modification to the ax.legend(... of your current code, to make the legend centered horizontally, with the top just below the axes:

# 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参数以适合我们图形的边界.

Here, the bbox_to_anchor argument should be customized to fit within the boundaries of our figure.

BlendedGenericTransform 允许以下项的转换x轴和y轴不同,这在许多情况下非常有用.

The BlendedGenericTransform allows the transforms of the x-axis and y-axis to be different, which can be very useful in many situations.

这篇关于matplotlib:组合不同的图形并将它们放在共享相同图例的单个子图中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆