jupyter notebook matplotlib figureframe changes size unexpectedly - python

I'm trying to have a jupyter notebook shows a progression of plots in a for loop. The code works, but for some reason the size of the figure changes after the for loop is done. Here's a set of minimal code to illustrate this (in jupyter notebook)
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
%matplotlib notebook
for i in range(10):
plt.gca().scatter(np.random.rand(10),
np.random.rand(10))
plt.gcf().canvas.draw()
plt.gcf().canvas.flush_events()
plt.pause(0.5)
A gif illustrating the issue is attached. This problem has been driving me crazy and changing margins or using tight_layouts() do not help. It seems to be related to how FigureFrame object is rendered. Thanks for the help!

Here comes the advantage of matplotlib.animation into play. It'll make sure the figure is completely drawn before starting the animation.
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def animate(i):
plt.gca().scatter(np.random.rand(10),
np.random.rand(10))
ani = FuncAnimation(plt.gcf(), animate, frames=10, interval=500)
plt.show()

Related

How to close matplotlib figures in jupyter notebook without conflicting with the backend?

I have written a small library, whose functions generate plots using this structure:
from matplotlib import pyplot as plt, rcParams, rc_context
with rc_context():
print(f'Figure backend {plt.get_backend()}')
x = [1,2,3,4,5]
y = [1,2,3,4,5]
fig, ax = plt.subplots()
ax.scatter(x,y)
plt.show()
plt.close(fig)
I would like this library to be compatible with jupyter notebooks but I am having issues with the backends.
For example: In "qt" backends the plot window is closed inmediatly and in "nbAgg" backends the plot is deleted. This code reproduces the issue.
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt, rcParams, rc_context
%matplotlib notebook
with rc_context():
ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))
ts = ts.cumsum()
ts.plot()
plt.close()
One solution is removing the plt.close(fig) but that would leave the figures opened.
Another option is adding some criteria to keep/close the figures depending on the backend, but from what I have seen the nomenclature changes from one OS to another, or if running from a notebook. The latter option is not easy though.
I wonder if anyone would please share their experience to keep the matplotlib figures in notebooks.

How to make group bars on jupyter notebook?

I am trying to plot multiple bars on the same plot on my jupyter notebook. However, due to some reason, it does not work on the notebook,but it works on a normal python editor. Here is the code that I have used.
import matplotlib.pyplot as plt
plt.bar(['A','B','C'],[72,73,88])
plt.bar(['A','B','C'],[98,77,98])
plt.show()
Any help will be highly appreciated.
(Edit)
I am looking for somthing like this on my jupyter notebook.
I presume you want to have both bar plots side by side. So here you go:
import matplotlib.pyplot as plt
fig,axs = plt.subplots(1,2)
axs[0].bar(['A','B','C'],[72,73,88])
axs[1].bar(['A','B','C'],[98,77,98])
plt.show()

Jupyter matplotlib inline mode with out-of-scope plt annotations

I have some plotting functions that are called in a jupyter notebook. The plotting functions include the calls
plt.figure()
and
plt.show()
However, the notebooks add annotations to the plot after the fact. The annotations work properly with
%matplotlib nbagg
but not
%matplotlib inline
which creates a new figure instead of annotating the old one (edit: this is the same behaviour as running a script in terminal). It seems that there's a scoping issue that nbagg circumvents and that inline does not. See below for a minimal reproducible example.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
def plotter():
plt.figure()
x = np.arange(-3,3,0.1)
y = np.exp(-x*x)
plt.scatter(x,y)
plt.show()
plotter()
plt.text(0, 0.5, 'gaus', horizontalalignment='center')
plt.show()
Question: is there a way I can get this to work in inline mode, e.g., by getting the most recently shown figure? I'd rather not edit the back-end plotting functions, which are not my own.

Matplotlib doesn't forget previous data when saving figures with savefig

import matplotlib.pyplot as plt
plt.plot([1,2,3],[1,2,3],'ro')
plt.axis([-4,4,-4,4])
plt.savefig('azul.png')
plt.plot([0,1,2],[0,0,0],'ro')
plt.axis([-4,4,-4,4])
plt.savefig('amarillo.png')
Output:
Why does this happen and how to solve?
What you see is a completely expected behaviour. You can plot as many data as often as you want to the same figure, which is very often very useful.
If you want to create several figures in the same script using the matplotlib state machine, you need to first close one figure before generating the next.
So in this very simple case, just add plt.close() between figure creation.
import matplotlib.pyplot as plt
plt.plot([1,2,3],[1,2,3],'bo')
plt.axis([-4,4,-4,4])
plt.savefig('azul.png')
plt.close()
plt.plot([0,1,2],[0,0,0],'yo')
plt.axis([-4,4,-4,4])
plt.savefig('amarillo.png')

Displaying image with matplotlib in ipython

How can I display an image imported with numpy package using matplotlib in ipython?
It should be fairly easy with the command
import numpy as np
import matplotlib.pyplot as plt
im = np.array(Image.open('image.jpg'))
plt.imshow(im)
But the image does not show and I just get the output
<matplotlib.image.AxesImage at 0x7fb38e10ff10>
You must call plt.show() to actually bring up the windows.
You can get around this by using interactive mode. But for scripts it is better to simply call show() after completing all your plotting commands.
In IPython or Jupyter notebooks, if you want to show images as inline in the notebook and not in a separate window, implement the code shown below.
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
im = np.array(Image.open('image.jpg'))
plt.imshow(im)
plt.show()

Categories

Resources