Reputation: 3635
How can the plot lines from .plot
be reused in subsequent plots?
I'd like to make plots on 4 axes, first three individual plot on each axes, and the last all 3 plots on last axes. Here is the code:
from numpy import *
from matplotlib.pyplot import *
fig=figure()
data=arange(0,10,0.01)
ax1=fig.add_subplot(2,2,1)
ax2=fig.add_subplot(2,2,2)
ax3=fig.add_subplot(2,2,3)
ax4=fig.add_subplot(2,2,4)
line1=ax1.plot(data,data)
line2=ax2.plot(data, data**2/10, ls='--', color='green')
line3=ax3.plot(data, np.sin(data), color='red')
#could I somehow use previous plots, instead recreating them all?
line4=ax4.plot(data,data)
line4=ax4.plot(data, data**2/10, ls='--', color='green')
line4=ax4.plot(data, np.sin(data), color='red')
show()
The resulting picture is:
Is there a way to define plots first and then add them to axes, and then plot them? Here is the logic I had in mind:
#this is just an example, implementation can be different
line1=plot(data, data)
line2=plot(data, data**2/10, ls='--', color='green')
line3=plot(data, np.sin(data), color='red')
line4=[line1, line2, line3]
Now plot line1 on ax1, line2 on ax2, line3 on ax3 and line4 on ax4.
Upvotes: 13
Views: 13047
Reputation: 8538
Line2D
plot Artist returned by plt.plot
can't be reused. Trying to do so, will result in a RuntimeError
as per def set_figure(self, fig):
line1
in the OP, is not the same as line1
created directly with the Line2D
method, because a plotted Artist has different properties.seaborn
, and API for matplotlib
, axes-level plots like seaborn.lineplot
return an axes
:
p = sns.lineplot(...)
then p.get_children()
to get the Artist objects.matplotlib.lines.Line2D
, and reused in multiple plots.python 3.8.11
, matplotlib 3.4.3
import numpy as np
from copy import copy
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
# crate the figure and subplots
fig, axes = plt.subplots(2, 2)
# flatten axes into 1-D for easy indexing and iteration
axes = axes.ravel()
# test data
data=np.arange(0, 10, 0.01)
# create test lines
line1 = Line2D(data, data)
line2 = Line2D(data, data**2/10, ls='--', color='green')
line3 = Line2D(data, np.sin(data), color='red')
lines = [line1, line2, line3]
# add the copies of the lines to the first 3 subplots
for ax, line in zip(axes[0:-1], lines):
ax.add_line(copy(line))
# add 3 lines to the 4th subplot
for line in lines:
axes[3].add_line(line)
# autoscale all the subplots if needed
for _a in axes:
_a.autoscale()
plt.show()
import numpy as np, copy
import matplotlib.pyplot as plt, matplotlib.lines as ml
fig=plt.figure(1)
data=np.arange(0,10,0.01)
ax1=fig.add_subplot(2,2,1)
ax2=fig.add_subplot(2,2,2)
ax3=fig.add_subplot(2,2,3)
ax4=fig.add_subplot(2,2,4)
#create the lines
line1=ml.Line2D(data,data)
line2=ml.Line2D(data,data**2/10,ls='--',color='green')
line3=ml.Line2D(data,np.sin(data),color='red')
#add the copies of the lines to the first 3 panels
ax1.add_line(copy.copy(line1))
ax2.add_line(copy.copy(line2))
ax3.add_line(copy.copy(line3))
[ax4.add_line(_l) for _l in [line1,line2,line3]] # add 3 lines to the 4th panel
[_a.autoscale() for _a in [ax1,ax2,ax3,ax4]] # autoscale if needed
plt.draw()
Upvotes: 7
Reputation: 76
Also this question has a good example of referencing to previous axes using:
fix, ax = plt.subplots(2, 2)
ax[0,1].plot(data, data**2 / 10, ls='--', color='g')
but also explains how to insert a title on each subplot using:
ax[0,1].set_title('Simple plot')
the dimension of ax depends on subplot parameters: if they are just tiled orizontally or vertically, ax will only need one index.
Upvotes: 0
Reputation: 2128
I had a simpler use case in jupyter notebooks. Given that you have stored a figure object somewhere, how can you replot it. eg:
Cell 1:
f = plt.figure(figsize=(18, 6))
f.suptitle("Hierarchical Clustring", fontsize=20)
dendrogram(Z, color_threshold=cut_off,
truncate_mode='lastp',
p=20)
Cell 2:
#plot f again, the answer is really simple
f
plt.show()
That's it. The benefit of that is you can store figures in objects and later use them when necessary.
Upvotes: 1
Reputation: 35269
I think your usage is fine, but you can pass all of the x,y
data pairs to plot
like this (although it makes it very horrible to read!):
ax4.plot(data, data, data, data**2 / 10, data, np.sin(data))
An amusing different way to do it is like this:
graph_data = [(data, data), (data, data**2 / 10), (data, np.sin(data))]
[ax4.plot(i,j) for i,j in graph_data]
Upvotes: 1