Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically changing dropdowns in IPython notebook widgets and Spyre

I have a dropdown in an IPython notebook (as part of the HTML widgets) and in a Spyre app (as a dropdown element), say to pick a continent and I'd like to add a second dropdown to select the country within the continent. Now obviously the options within the second dropdown are dependent on the value of the first one. I'm struggling to find a convenient way to have a callback function that would update this UI element.

I have almost done this in the IPython notebook where I had one interact function and within the called function, I'd create a second interact element with the second dropdown. But whenever I'd change the first dropdown a new dropdown element would be created, so I'd end up with one additional dropdown with each change. But I only want one dropdown to be updated, that's all.

Hope the issue is clear. Thank you.

like image 567
Ondrej Avatar asked Feb 15 '15 17:02

Ondrej


People also ask

What is Python Ipywidgets?

ipywidgets, also known as jupyter-widgets or simply widgets, are interactive HTML widgets for Jupyter notebooks and the IPython kernel. Notebooks come alive when interactive widgets are used. Users gain control of their data and can visualize changes in the data.

How do you interact in a Jupyter notebook?

At the most basic level, interact autogenerates UI controls for function arguments, and then calls the function with those arguments when you manipulate the controls interactively. To use interact , you need to define a function that you want to explore. Here is a function that returns its only argument x .


2 Answers

Use interactive instead of interact and update your widget:

from IPython.html import widgets
from IPython.display import display

geo={'USA':['CHI','NYC'],'Russia':['MOW','LED']}

def print_city(city):
    print city

def select_city(country):
    cityW.options = geo[country]


scW = widgets.Select(options=geo.keys())
init = scW.value
cityW = widgets.Select(options=geo[init])
j = widgets.interactive(print_city, city=cityW)
i = widgets.interactive(select_city, country=scW)
display(i)
display(j)
like image 119
ILoveCoding Avatar answered Sep 26 '22 20:09

ILoveCoding


The answer with the most up-votes is useful but seems a bit clumsy for me. After searching for a while, I found the answer here based on Jupyter docs is more preferred for me. I adapted them and provide the following.

from ipywidgets import interact, Dropdown

geo = {'USA':['CHI','NYC'],'Russia':['MOW','LED']}
countryW = Dropdown(options = geo.keys())
cityW = Dropdown()

def update_cityW_options(*args): # *args represent zero (case here) or more arguments.
    cityW.options = geo[countryW.value]
cityW.observe(update_cityW_options) # Here is the trick, i.e. update cityW.options based on countryW.value.

@interact(country = countryW, city = cityW)
def print_city(country, city):
    print(country, city)

As an alternative, I also found that I can just update the cityW.options within print_city function, an even clearer practice!

from ipywidgets import interact, Dropdown

geo = {'USA':['CHI','NYC'],'Russia':['MOW','LED']}
countryW = Dropdown(options = geo.keys())
cityW = Dropdown()

@interact(country = countryW, city = cityW)
def print_city(country, city):
    cityW.options = geo[country] # Here is the trick, i.e. update cityW.options based on country, namely countryW.value.
    print(country, city)
like image 42
Fei Yao Avatar answered Sep 23 '22 20:09

Fei Yao