Matplotlib: combine different numbers and put them in a single subtitle that uses a common legend

We have code that creates numbers from input.txt files . We need to combine 2 of these numbers in one subtitle. The data from Figure 1 will be displayed in the left subtitle and in Figure 2 in the right subtitle using the same legend and with the same scale in the x and y axes:

enter image description here

Here are some sample 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 very convenient to transfer the ax1 and ax2 objects to the new shape, since they have much more information. There seems to be no easy way to achieve this .

The real case was available here . For it to work, run plot_both.py .


EDIT2: It was easier to change the procedure that reads input.txt files. Now it supports multiple graphs . But the question remains valid, because it would be great to consider AxesSubplot as an easily interchangeable object between different figures, subtitles, etc ...

+9
source share
1 answer

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 the result as shown below. enter image description here

Edit

Having looked at the code in the downloaded zip file, I would say that most of the requested functions have been achieved?

I see that you changed the function that creates the plots, which radically changed the solution to your problem, since you are no longer trying to "combine" the two subheadings from different numbers. Your solution is basically the same as the one I presented above, in the sense that both instances of Axes created as subtitles in the same picture (giving the desired layout), and then print the picture, and not print it, and then the axes are removed / moved as your question was originally about.

As I suspected, the simplest and most trivial solution is to create separate Axes linings of the same figure instead of tying them to separate figures, since moving one instance of Axes from one Figure to another is not easy (if at all possible), as indicated in the comment. The "original" problem is still very complex, since simply adding an Axes instance to Figure _axstack makes it difficult to customize the desired layout.

One modification of ax.legend(... your current code to make the legend centered horizontally, with a vertex 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)) 

Here, the argument bbox_to_anchor must be configured so that it matches the borders of our figure.

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

+9
source

Source: https://habr.com/ru/post/945833/


All Articles