Python: ipywidgets not showing output

Question:

I wrote a python script that should have a data frame as output, but it does not show any output. Below is the python code:

import pandas as pd
import numpy as np
import ipywidgets as widgets
import datetime
from ipywidgets import interactive
from IPython.display import display, Javascript
from datetime import date, timedelta
from random import choices
  

books = ["Book_1","Book_2","Book_3","Book_4","Book_5"]
counterparties = ["Counterparty_1","Counterparty_2","Counterparty_3","Counterparty_4","Counterparty_5"]

book = choices(books, k = 100)
counterparty = choices(counterparties, k = 100)


date1, date2 = date(2018, 8, 1), date(2023, 8, 3)
  
res_dates = [date1]
  
while date1 != date2:
    date1 += timedelta(days=1)
    res_dates.append(date1)
  
ldd = choices(res_dates, k=100)

dict = {'book': book, 'counterparty': counterparty, 'last_trading_date': ldd} 

df = pd.DataFrame(dict)



books = pd.Categorical(df['book'])
books = books.categories

books_dropdown = widgets.Dropdown(
    options=books,
    value=books[0],
    description='Book:',
    disabled=False,
)


counterparty = pd.Categorical(df['counterparty'])
counterparty = counterparty.categories

counter_dropdown = widgets.Dropdown(
    options=counterparty,
    value=counterparty[0],
    description='Counterparty:',
    disabled=False,
)


date_picker = widgets.DatePicker(
    description='Pick a Date',
    disabled=False,
)
date_picker.add_class("start-date")

script = Javascript("
                const query = '.start-date > input:first-of-type'; 
                document.querySelector(query).setAttribute('min', '2020-12-01'); 
                document.querySelector(query).setAttribute('max', '2025-01-01'); 
        ")


box = widgets.VBox([books_dropdown, counter_dropdown, date_picker])
display(box)

def filter_function(bookcode, cpartycode, datecode):
        
    filtered = df[(df['book'] == bookcode) & (df['counterparty'] == cpartycode)]
    
    x = datetime.date(datecode.value)
    
    filtered = filtered[filtered['last_trading_date'] < x]
    
    with report_output:
        report_output.clear_output()
        display(filtered)
        
interactive(filter_function, bookcode=books_dropdown, cpartycode=counter_dropdown, datecode=date_picker) 

report_output = widgets.Output()
display(report_output)

What this does is basically take a data frame, subset the said data frame into a smaller data frame based on categories of two variables, and truncate the resulting data frame based on a date selected by the user.

Did I make a mistake somewhere? If so, can someone point to me where? Thank you in advance.

Edit:

After many attempts I came to the conclusion that the problem is related to the DatePicker widget. So you can focus on that when trying to solve the problem.

Asked By: Saïd Maanan

||

Answers:

Here is the code I used to reproduce the issue if I understand it correctly:

from datetime import date, timedelta
from random import choices 
import pandas as pd
import ipywidgets as widgets
import datetime
from ipywidgets import interactive
from IPython.display import display, Javascript

books = ["Book_1","Book_2","Book_3","Book_4","Book_5"]
counterparties = ["Counterparty_1","Counterparty_2","Counterparty_3","Counterparty_4","Counterparty_5"]

book = choices(books, k = 100)
counterparty = choices(counterparties, k = 100)

date1, date2 = date(2018, 8, 1), date(2023, 8, 3)
res_dates = [date1]
  
while date1 != date2:
    date1 += timedelta(days=1)
    res_dates.append(date1)
  
ldd = choices(res_dates, k=100)
dict = {'book': book, 'counterparty': counterparty, 'last_trading_date': ldd} 

df = pd.DataFrame(dict)
df['last_trading_date'] = pd.to_datetime(df['last_trading_date'], format = '%Y-%m-%d').dt.date

books = pd.Categorical(df['book'])
books = books.categories

books_dropdown = widgets.Dropdown(
    options=books,
    value=books[0],
    description='Book:',
    disabled=False,)

counterparty = pd.Categorical(df['counterparty'])
counterparty = counterparty.categories

counter_dropdown = widgets.Dropdown(
    options=counterparty,
    value=counterparty[0],
    description='Counterparty:',
    disabled=False,
)

date_picker = widgets.DatePicker(
    description='Pick a Date',
    disabled=False,
)

date_picker.add_class("start-date")

script = Javascript("
                const query = '.start-date > input:first-of-type'; 
                document.querySelector(query).setAttribute('min', '2020-12-01'); 
                document.querySelector(query).setAttribute('max', '2025-01-01'); 
        ")

def filter_function(bookcode, cpartycode, datecode):
    filtered = df[(df['book'] == bookcode) & (df['counterparty'] == cpartycode)]
    filtered = filtered[filtered['last_trading_date'] < datecode]
    with report_output:
        report_output.clear_output()
        display(filtered)  
        
w = interactive(filter_function, bookcode=books_dropdown, cpartycode=counter_dropdown, datecode=date_picker) 

display(w)
report_output = widgets.Output()
display(report_output)

Using the widget that’s displayed when the code is run in Jupyter Notebook, I get the following output:

enter image description here

Only changes that I made in the code provided by you are:

  1. Remove the code for VBox.
  2. Store interactive widget as a variable and use display() to display it.
  3. Directly use datecode argument to filtered_function for creating filtered instead of using datetime.date(datecode.value).
Answered By: medium-dimensional