Search code examples
pythonipywidgetsvoila

How to load data using ipywidgets and display it in modern Jupyter


I am trying to load a sample Excel file to test a functionality, which ultimately will have to be rendered through Voila. Let alone perform an operation on the Dataframe and make it available for download as Excel file, I am not even able to even see the Dataframe. I don't even know if I am loading the Dataframe or not.

import ipywidgets as widgets    
def load_data():
    df = pd.read_excel('....xlsx',engine='openpyxl',dtype=str)
    display(df)    
def on_sample_data_click(event):
    load_data()

text_caption = widgets.HTML(value="<h2>Showing data</h1><h2>")
vbox_text = widgets.VBox([text_caption])
display(vbox_text)

load_sample_data = widgets.Button(description='Click to show', layout=dict(width='auto', height='auto'))
load_sample_data.on_click(on_sample_data_click)
display(load_sample_data)

The display is this:

enter image description here

Now, when I click on Click to show I had expected Dataframe be displayed, but nothing shows up.

Any help would be highly appreciated.


Solution

  • The main issue is spelled at the top here. That summarizes the issue as:

    "I suspect you are thinking things aren't working when they are. (Hence, no errors.) However, in modern ipywidgets and Jupyter you have to be explicit in how you connect up the output being generated to the output area of the cell."

    This is your code changed to add that handling via an approach to add a with context manager to direct the output to an Output widget (you'll need to adjust the file path/name for the .xlsx file to match your own):

    import ipywidgets as widgets
    from IPython.display import display
    output = widgets.Output()
    import pandas as pd
    def load_data():
        df = pd.read_excel('sample-1-sheet.xlsx',engine='openpyxl',dtype=str)
        with output:
            output.clear_output() # from 'Output widgets: leveraging Jupyter’s display system' https://ipywidgets.readthedocs.io/en/latest/examples/Output%20Widget.html
            display(df)
    def on_sample_data_click(event):
        load_data()
    
    text_caption = widgets.HTML(value="<h2>Showing data</h1><h2>")
    vbox_text = widgets.VBox([text_caption])
    display(vbox_text)
    
    load_sample_data = widgets.Button(description='Click to show', layout=dict(width='auto', height='auto'))
    load_sample_data.on_click(on_sample_data_click)
    display(load_sample_data)
    display(output)
    

    Details

    My comment here spells out how I edited your code to add that handling of linking the display of the dataframe to the output area via a context manager. You'll probably want to read ipywidget's documentation on 'Output widgets: leveraging Jupyter’s display system'. (There's more example code linked there.)

    For easier developing with ipywidgets, you'll want to consider using JupyterLab. When I ran your code there, I could see in the Log console that the event was happening (lights up in bottom, left-ish of JupyterLab window when output directed there), see my comment here for more about this.
    Even though I developed this in JupyterLab, I did verify it worked in Voila by testing that rendering of the notebook as well, see below.

    Demonstration in Voila and Jupyter notebook rendering

    To demonstrate in Voila, click here.
    To demonstrate that in a notebook click here to launch a notebook that you can step through running demonstrating this in a session served via the MyBinder service. Or go here, then use this notebook here or the content from it.