Is there any way to change data from a matplotlib plot after it has been created and showed?

Question:

So I have a function that prints me some plot once called, and returns some other data. The code for the plot is this one

def somefunction(input):

     x = np.linspace(-5,5,100)
     fig, axs = plt.subplots(2,sharex=True)
     fig.suptitle("Some plots")

     axs[0].plot(x, x**2, "-b", label="square")
     axs[1].plot(x, x**3, "-y", label="cube")

     axs[0].set(ylabel="values")
     axs[1].set(xlabel="Timestamp (common)", ylabel="values")

     axs[0].legend()
     axs[1].legend()
 
     plt.show()
     

     return [1,2,3]

Now, what I want to do is to print this plot later again but with additional information. I thought about saving the figure created here as the output of the function. I tried to do this by adding this to the code:

def somefunction(input):

    x = np.linspace(-5,5,100)
    fig, axs = plt.subplots(2,sharex=True)
    fig.suptitle("Some plots")

    axs[0].plot(x, x**2, "-b", label="square")
    axs[1].plot(x, x**3, "-y", label="cube")

    axs[0].set(ylabel="values")
    axs[1].set(xlabel="Timestamp (common)", ylabel="values")

    axs[0].legend()
    axs[1].legend()

    plt.show()
    fig_out = fig

    return [1,2,3], fig_out

and then later I can just obtain the figure in the second component of the output of the function and change it as I want. Like:

figure = somefunction(input)[1]
#now perform any wanted changes in the plot and plot again
ax0 = figure.axes[0]
ax0.text(3, 8, 'New text updated in the figure', style='italic',
    bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})

plt.show()

This doesn’t work. The figure is indeed, saved in the second component of the output, but it doesn’t let me change anything about it. It’s just there, and I can’t change it, nor plot any changes made to the figure.

I also tried saving the axes instead of the figure, but same story. I can’t seem to find a way to edit this plot after it was created. Is it even possible?

Asked By: puradrogasincortar

||

Answers:

Your code is fine, if you don’t try to show both plots at once. There are multiple options to solve it, for instance:

Option 1: show the plot at the end

from matplotlib import pyplot as plt

def somefunction(input):
    x = np.linspace(-5,5,100)
    fig, axs = plt.subplots(2,sharex=True)
    fig.suptitle("Some plots")

    axs[0].plot(x, x**2, "-b", label="square")
    axs[1].plot(x, x**3, "-y", label="cube")

    axs[0].set(ylabel="values")
    axs[1].set(xlabel="Timestamp (common)", ylabel="values")

    axs[0].legend()
    axs[1].legend()

    #plt.show() #<- DO NOT USE IT NOW

    return [1,2,3], fig

my_fig = somefunction(input)[1]
ax0 = my_fig.axes[0]
ax0.text(3, 8, 'New text updated in the figure', style='italic', bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})

plt.show()

Option 2: use block=False to indicate to wait until all figures are returned

def somefunction(input):
    x = np.linspace(-5,5,100)
    fig, axs = plt.subplots(2,sharex=True)
    fig.suptitle("Some plots")

    axs[0].plot(x, x**2, "-b", label="square")
    axs[1].plot(x, x**3, "-y", label="cube")

    axs[0].set(ylabel="values")
    axs[1].set(xlabel="Timestamp (common)", ylabel="values")

    axs[0].legend()
    axs[1].legend()

    plt.show(block=False) #<- USE BLOCK=FALSE

    return [1,2,3], fig

my_fig = somefunction(input)[1]
ax0 = my_fig.axes[0]
ax0.text(3, 8, 'New text updated in the figure', style='italic', bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})

plt.show()
Answered By: flyakite
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.