How to make the plot not disappear? - python

Suppose you need to store the figure and subplot in variables (to later modify attributes). How can you make the whole figure to stay and not quickly disappear after some millisecs?
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(2,2,1)
ax.plot(1)
fig.show()

Change fig to plt:
plt.show()

Related

fixing the y scale in python matplotlib

I want to draw multiple bar plots with the same y-scale, and so I need the y-scale to be consistent.
For this, I tried using ylim() after yscale()
plt.yscale("log")
plt.ylim(top=2000)
plt.show()
However, python keeps autoscaling the intermittent values depending on my data.
Is there a way to fix this?
overlayed graphs
import numpy as np
import matplotlib.pyplot as plt
xaxis = np.arange(10)
yaxis = np.random.rand(10)*100
fig = plt.subplots(figsize =(10, 7))
plt.bar(xaxis, yaxis, width=0.8, align='center', color='y')
# show graph
plt.yscale("log")
plt.ylim(top=2000)
plt.show()
You can set the y-axis tick labels manually. See yticks for an example. In your case, you will have to do this for each plot to have consistent axes.

matplotlib: Setting single title for all figures (not subplots)

I want to give all the figures in my code a single title #Variable_cycles. Figures are not subplots but plotted separately. I am using %matplotlib to show plots in separate window. As far as i know plt.rcParams has no such key
import matplotlib.pyplot as plt
%matplotlib
plt.figure(1), plt.scatter(x,y,marker='o'),
plt.title("Variable_cycles"),
plt.show
plt.figure(2),
plt.scatter(x,y,marker='*'),
plt.title("Variable_cycles"),
plt.show
I don't believe there is such a setting in rcParams or similar, but if there are options you are setting for all figures, you could create a simple helper function to create the figure, apply those settings (e.g. the title, axes labels, etc), and return the figure object, then you just need to call that function once for each new figure. A simple example would be:
import matplotlib.pyplot as plt
%matplotlib
def makefigure():
# Create figure and axes
fig, ax = plt.subplots()
# Set title
fig.suptitle('Variable cycles')
# Set axes labels
ax.set_xlabel('My xlabel')
ax.set_ylabel('My ylabel')
# Put any other common settings here...
return fig, ax
fig1, ax1 = makefigure()
ax1.scatter(x, y, marker='o')
fig2, ax2 = makefigure()
ax2.scatter(x, y, marker='*')

Matplotlib copy/duplicate a 3D figure?

I've tried to find a way to copy a 3D figure in matplotlib but I didn't find a solution which is appropriate in my case.
From these posts
How do I reuse plots in matplotlib?
and
How to combine several matplotlib figures into one figure?
Using fig2._axstack.add(fig2._make_key(ax),ax) as in the code below gives quite the good result but figure 2 is not interactive I can't rotate the figure etc :
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(1)
ax = fig.gca(projection = '3d')
ax.plot([0,1],[0,1],[0,1])
fig2 = plt.figure(2)
fig2._axstack.add(fig2._make_key(ax),ax)
plt.show()
An alternative would be to copy objects from ax to ax2 using a copy method proposed in this post How do I reuse plots in matplotlib? but executing the code below returns RuntimeError: Can not put single artist in more than one figure :
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np, copy
fig = plt.figure(1)
ax = fig.gca(projection = '3d')
ax.plot([0,1],[0,1],[0,1])
fig2 = plt.figure(2)
ax2 = fig2.gca(projection = '3d')
for n in range(len(ax.lines)) :
ax2.add_line(copy.copy(ax.lines[n]))
plt.show()
Those codes are pretty simple but I don't want to copy/paste part of my code for drawing similar figures
Thanks in advance for your reply !

Using plt functions on figures in matplotlib or passing plt to mpld3

Many examples define fig and ax with fig, ax = plt.subplots() and then they directly call functions on the figure object. In contrast, other examples work directly with plt. This answer explains some of the differences, but I am still unclear about two things. First, if I do not create a separate figure object, how do I pass it to another function. For example, when I create a figure object I can pass it to mpld3 to create D3 visualization:
d3plot = mpld3.fig_to_html(fig,template_type="simple")
Second, if I do create the figure object then how do I call functions that I can call on plt on the figure? For example, I would like to able to run the following code and then pass it as a figure to mpld3 as above.
plt.imshow(wordcloud)
plt.axis("off")
plt.show()
The other answer says that plt.subplots() unpacks a tuple. I was not sure if it would unpack what was already on the plt. So I tried:
wordcloud = WordCloud().generate(text)
plt.imshow(wordcloud)
plt.axis("off")
fig, ax = plt.subplots()
d3plot = mpld3.fig_to_html(fig,template_type="simple")
However, this just gives me a black plot, which is consistent with my prior understanding that plt.subplots() creates entirely new figures.
Update
Based on the comments, I tried the following:
wordcloud = WordCloud().generate(text)
figTopicWordCloud, ax = plt.subplots()
ax.imshow(wordcloud)
ax.axis('off')
d3plot = mpld3.fig_to_html(figTopicWordCloud, template_type="simple")
While this successfully produced the plot, it did not remove the axes from the figure.
When you run something like
plt.imshow()
without explictly creating a figure before, matplotlib creates a new figure object and a new axes object. To access the figure use
fig = plt.gcf()
This returns the current figure. Similarly,
ax = fig.gca()
gives you a reference to the currently active axes in that figure. Calling
fig, ax = plt.subplots()
however, is short for the following:
fig = plt.figure()
ax = fig.add_subplot(111)
The first line will create an entirely new figure object.
A quick solution for your case it to plot the data and access the implicitly created figure after that, like so:
plt.imshow(wordcloud)
plt.axis("off")
fig = plt.gcf()
d3plot = mpld3.fig_to_html(fig, template_type="simple")
You could also explicitly create the figure before actually plotting. Your example would become
fig = plt.figure()
ax = fig.gca()
ax.imshow(wordcloud)
ax.set_axis_off()
d3plot = mpld3.fig_to_html(fig, template_type="simple")
I would usually recommend this solution, because you can always be sure that you are plotting to the correct figure. This is especially useful when handling multiple figures at a time.

Changing matplotlib subplot size/position after axes creation

Is it possible to set the size/position of a matplotlib subplot after the axes are created? I know that I can do:
import matplotlib.pyplot as plt
ax = plt.subplot(111)
ax.change_geometry(3,1,1)
to put the axes on the top row of three. But I want the axes to span the first two rows. I have tried this:
import matplotlib.gridspec as gridspec
ax = plt.subplot(111)
gs = gridspec.GridSpec(3,1)
ax.set_subplotspec(gs[0:2])
but the axes still fill the whole window.
Update for clarity
I want to change the position of an existing axes instance rather than set it when it is created. This is because the extent of the axes will be modified each time I add data (plotting data on a map using cartopy). The map may turn out tall and narrow, or short and wide (or something in between). So the decision on the grid layout will happen after the plotting function.
Thanks to Molly pointing me in the right direction, I have a solution:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
fig = plt.figure()
ax = fig.add_subplot(111)
gs = gridspec.GridSpec(3,1)
ax.set_position(gs[0:2].get_position(fig))
ax.set_subplotspec(gs[0:2]) # only necessary if using tight_layout()
fig.add_subplot(gs[2])
fig.tight_layout() # not strictly part of the question
plt.show()
You can create a figure with one subplot that spans two rows and one subplot that spans one row using the rowspan argument to subplot2grid:
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = plt.subplot2grid((3,1), (0,0), rowspan=2)
ax2 = plt.subplot2grid((3,1), (2,0))
plt.show()
If you want to change the subplot size and position after it's been created you can use the set_position method.
ax1.set_position([0.1,0.1, 0.5, 0.5])
Bu you don't need this to create the figure you described.
You can avoid ax.set_position() by using fig.tight_layout() instead which recalculates the new gridspec:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
# create the first axes without knowing of further subplot creation
fig, ax = plt.subplots()
ax.plot(range(5), 'o-')
# now update the existing gridspec ...
gs = gridspec.GridSpec(3, 1)
ax.set_subplotspec(gs[0:2])
# ... and recalculate the positions
fig.tight_layout()
# add a new subplot
fig.add_subplot(gs[2])
fig.tight_layout()
plt.show()

Categories