How to display matplotlib plots in a Jupyter tab widget?

Arthur Azevedo De Amorim picture Arthur Azevedo De Amorim · Jun 13, 2018 · Viewed 9.5k times · Source

I am having trouble displaying plots inside of Jupyter tab widgets. Consider the following snippet:

import matplotlib.pyplot as plt
import pandas as pd
import ipywidgets as widgets
import numpy as np

out1 = widgets.Output()
out2 = widgets.Output()
data1 = pd.DataFrame(np.random.normal(size = 50))
data2 = pd.DataFrame(np.random.normal(size = 100))

with out1:
    fig1, axes1 = plt.subplots()
    data1.hist(ax = axes1)
    display(fig1)

with out2:
    fig2, axes2 = plt.subplots()
    data2.hist(ax = axes2)
    display(fig2)

tab = widgets.Tab(children = [out1, out2])
tab.set_title(0, 'First')
tab.set_title(1, 'Second')
display(tab)

(I am running Python 3.5.2, Jupyter 4.4.0, ipywidgets 7.2.1 on Ubuntu 16.04 inside a virtual environment.)

If I put this code on the first row of the notebook and run it, I see a tab widget with two tabs, each one of which displays a string, but not the plot:

No plots

If I run it for a second time, or if I rerun it putting everything after the import of matplotlib in a second cell, I see a tab widget with one plot on each tab, but I get the two plots displayed a second time outside of the tabs.

Too many plots

I can get rid of the additional displays by wrapping my code inside calls to plt.ioff and plt.ion, but it has been suggested to me that this is a hack. And in any case, it does not make matplotlib display the plots in the first cell.

Question: What is the proper way of displaying plots inside tabs?

Answer

ac24 picture ac24 · Jun 27, 2018

I added a couple of things to make your code work as you would like

  • Add %matplotlib inline at the top of the cell
  • Replace your display(fig) calls with plt.show(fig) calls.
%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import ipywidgets as widgets
import numpy as np

out1 = widgets.Output()
out2 = widgets.Output()
data1 = pd.DataFrame(np.random.normal(size = 50))
data2 = pd.DataFrame(np.random.normal(size = 100))

tab = widgets.Tab(children = [out1, out2])
tab.set_title(0, 'First')
tab.set_title(1, 'Second')
display(tab)

with out1:
    fig1, axes1 = plt.subplots()
    data1.hist(ax = axes1)
    plt.show(fig1)

with out2:
    fig2, axes2 = plt.subplots()
    data2.hist(ax = axes2)
    plt.show(fig2)