How to Display Objects in Jupyter in Tabular Layout

Jupyter notebooks are a great tool for exploring ideas and for writing scientific or mathematical documents. But there is one thing that annoyed me all the time: there seemed to be no easy way to display objects side by side. Instead, if you display several objects, it will display them vertically one after another. But there is a way to display side by side and this post shows you a way how to do it.

Suppose we want to create a little integral table. The first column shall be the integrand 𝑓(𝑥), the second column shall be the indefinite integral

Using sympy , one would usually start writing something like this, but of course, this will display all results vertically. This is NOT what we want. Look:

from sympy import *
from sympy.abc import x, n

fs = [x**n, sin(x), cos(x), exp(x)]

for f in fs:
    display(f)
    integ = integrate(f, x)
    display(integ)

If you want to display several items in a row, you can use the ipywidgets package. Simply use pip to install it:

pip install ipywidgets

ipywidgets contains a lot of typical widgets like input boxes, buttons, sliders, color pickers, etc. But the one we will use is the raw Output widget. It is convenient because it allows putting any kind of rich IPython output. Output will serve to display a single cell of our table. The layout of the table is handled by another class from ipywidget : GridspecLayout . Its usage is quite intuitive. Nevertheless, it's practical to wrap it in a function:

from ipywidgets import GridspecLayout

def display_table(table_data):
    """Display data in a table layout in Jupyter."""
        
    nrows = len(table_data)
    ncols = len(table_data[0])
    
    grid = GridspecLayout(nrows, ncols)

    for row_idx, row_data in enumerate(table_data):
        for col_idx, col in enumerate(row_data):
            out = Output()
            with out:
                display(col)
                grid[row_idx, col_idx] = out

    display(grid)

Using this function, we can gather — row by row — the items we want to display and then call our helper function:

from sympy import *
from sympy.abc import x, n

fs = [x**n, sin(x), cos(x), exp(x)]

rows = []
for f in fs:
    integ = Integral(f, x)
    result = integrate(f, x)
    rows.append([integ, result])

display_table(rows)

And that’s exactly what we wanted it to look like. The GridspecLayout has a lot of properties and you can adjust its look to whatever you want, as it leverages the full power of CSS. But that's beyond the scope of this little post, which is intended to get you started so that you know what to look for when you want to dig deeper.