1

I have a simple base plot generated by the following code:

import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [1, 2, 3], label="basic plot")

Moreover, I have several additional plots that I would like each one of them to be plotted over the basic plot above, but separately. For example, if I call the above plot "basic plot", and I also have plots "additional_1" and "additional_2", then I would like to get two final plots:

  1. basic plot + additional_1
  2. basic plot + additional_2

I could of course finish with the first plot (1.), and then re-generate "basic plot", and plot "additional_2" over it, but since the creation of "basic plot" is more complex than the example described, I would like to avoid it, that is, I don't want to create the base plot multiple times.

Is there a way to plot the basic plot, and then "copy" it to multiple figs, and plot the additional figs separately on each fig? Is there any other way to achieve the same? If not, is it possible to "undo" the last (additional_1) plot, and to plot another (additional_2) instead (after saving or showing the fig)?

Here is some toy code for the additional plots: (I don't want them to be plotted together)

plt.plot([1.5, 2, 2.5], [0, 5, 2], label="additional_1")
plt.plot([2, 2.5, 3], [6, 0, 3], label="additional_2")

Thanks

tdy
  • 36,675
  • 19
  • 86
  • 83
  • Does this answer your question? [pyplot - copy an axes content and show it in a new figure](https://stackoverflow.com/questions/45810557/pyplot-copy-an-axes-content-and-show-it-in-a-new-figure) – BigBen Mar 04 '22 at 18:40
  • No, for several reasons: 1. This question is old (3 years), and the provided walkaround (using pickle) might have a formal better solution now (or not?) 2. This solution regards deleting an ax, whereas I'm trying to undo a plot operation on it (is it possible to place multiple axes one over the other and not one next to the other?) 3. The other solution requires me to re-generate the basic plot, which is impossible in my case. – Matan Solomon Mar 04 '22 at 19:06
  • 3
    I'm not sure exactly what the end goal is, but you probably should be using the object-oriented interface of matplotlib: `fig, ax = plt.subplots(), ax.plot(...)`, and maybe creating (reusable) functions with an `ax` parameter. – BigBen Mar 04 '22 at 19:28
  • I concur that BigBen's suggestion to create reusable functions with an `ax` as parameter is the logical and most straightforward way to go. Saving the plot to a buffer and reading it again is prone to many problems, without any benefit. – JohanC Mar 04 '22 at 20:47

2 Answers2

2
  1. That question is old (3 years), and the provided workaround (using pickle) might have a formal better solution now (or not?)

I'm not aware of a newer way to do this.

  1. This solution regards deleting an ax, whereas I'm trying to undo a plot operation on it

BigBen's link involves click events, but the general idea of pickling is the same. My figure pickling answer is a bit more straightforward, but I'll demonstrate your use case here.

  1. Save basic_plot as a pickle:

    import pickle
    
    fig, ax = plt.subplots()
    ax.plot([1, 2, 3], [1, 2, 3], label='basic_plot')
    pickle.dump(fig, open('basic_plot.pkl', 'wb'))
    
  2. Now say tomorrow you want to reload basic_plot and overlay additional_1. Load the pickled figure and plot additional_1 onto axes[0] (or the respective index if you have multiple subplots):

    fig1 = pickle.load(open('basic_plot.pkl', 'rb'))
    fig1.axes[0].plot([1.5, 2, 2.5], [0, 5, 2], 'r--', label='additional_1')
    fig1.legend()
    

  3. If later you want to combine basic_plot with additional_2, rinse and repeat:

    fig2 = pickle.load(open('basic_plot.pkl', 'rb'))
    fig2.axes[0].plot([2, 2.5, 3], [6, 0, 3], 'r--', label='additional_2')
    fig2.legend()
    

tdy
  • 36,675
  • 19
  • 86
  • 83
1

Plot returns a list of Line2D objects. You can access the object properties, in particular its x and y coordinates and use them in another plot like this:

fig, ax = plt.subplots(1,2)
L1 = ax[0].plot([1, 2, 3], [1, 2, 3], label="basic plot")
ax[0].plot([1.5, 2, 2.5], [0, 5, 2], label="additional1")
ax[0].legend()

ax[1].plot(L1[0].get_xdata(), L1[0].get_ydata(), label="basic plot")
ax[1].plot([2, 2.5, 3], [6, 0, 3], label="additional2")
ax[1].legend()
plt.show()
rehaqds
  • 414
  • 2
  • 6