4

I was following the example on how to handle multiple dependent widgets on jupyter notebooks from here:

Dynamically changing dropdowns in IPython notebook widgets and Spyre

In that example the code solution was the following:

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.Dropdown(options=geo.keys())
init = scW.value
cityW = widgets.Dropdown(options=geo[init])
j = widgets.interactive(print_city, city=cityW)
i = widgets.interactive(select_city, country=scW)
display(i)
display(j)

so, the second dropdown is dependent on the value of the first one. Here the question: What if i want to create a third dropdown that is dependent on the value of the second one? Let's say that each of the cities above (CHI, NYC, MOW, LED) have some districts, and I'd like a third dropdown that change every time that a city is updated.

Hope that the problem is clear, thank you!

davidvarenne
  • 141
  • 1
  • 2
  • 11
  • https://stackoverflow.com/questions/62258847/using-multiple-depended-widgets-from-jupyter-notebook-and-interactive-problem – Eichstier Jun 08 '20 at 09:29
  • hey can you check this out? https://stackoverflow.com/questions/62258847/using-multiple-depended-widgets-from-jupyter-notebook-and-interactive-problem I could need some help – Eichstier Jun 08 '20 at 09:30

2 Answers2

3

Just in case you never found a solution: I have one here that works in python 3. I've commented everything that I changed from the original code. I hope it helps!

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

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

geo2={'CHI':['1','2'],'NYC':['3','4'],'MOW':['5','6'],'LED':['7','8']} #create dictionary with city districts

def print_city(city,district):
    print(city)
    print(district) #add in command to print district

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

#add in 'select district' function that looks in the new dictionary
def select_district(city):
    districtW.options = geo2[city]

scW = widgets.Dropdown(options=geo.keys())
init = scW.value
cityW = widgets.Dropdown(options=geo[init])


init2= cityW.value #new start value for district dropdown
districtW = widgets.Dropdown(options=geo2[init2]) #define district dropdown widget

j = widgets.interactive(print_city, city=cityW, district=districtW) #define district value
i = widgets.interactive(select_city, country=scW)

k = widgets.interactive(select_district, city=cityW) #call everything together with new interactive

display(i)
display(j)
AaylaSecura
  • 43
  • 1
  • 6
3

Using interactive is somewhat clumsy for me. I have provided an answer clearer and conciser for two dependent widgets in the original page here. Below I provide my answer for multiple dependent widgets.

from ipywidgets import interact, Dropdown

geo = {'USA':['CHI','NYC'],'Russia':['MOW','LED']}
geo2={'CHI':['1','2'],'NYC':['3','4'],'MOW':['5','6'],'LED':['7','8']}

countryW = Dropdown(options = geo.keys())
cityW = Dropdown(options = geo[countryW.value]) # options = geo[countryW.value] is to remove inital error but not that necessary.
districtW = Dropdown()

@interact(country = countryW, city = cityW, district = districtW)
def print_city(country, city, district):
    cityW.options = geo[country] # Here is the trick, i.e. update cityW.options based on country, namely countryW.value.
    districtW.options = geo2[city] # Dittoo
    print(country, city, district)

An alternative would be to use explicit update functions shown as follows. Bear in mind that the update speed may not be that quick. The code works well.

from ipywidgets import interact, Dropdown

geo = {'USA':['CHI','NYC'],'Russia':['MOW','LED']}
geo2={'CHI':['1','2'],'NYC':['3','4'],'MOW':['5','6'],'LED':['7','8']}

countryW = Dropdown(options = geo.keys())
cityW = Dropdown()
districtW = 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.

def update_districtW_options(*args):
    districtW.options = geo2[cityW.value]
districtW.observe(update_districtW_options)

@interact(country = countryW, city = cityW, district = districtW)
def print_city(country, city, district):
    print(country, city, district)
Fei Yao
  • 1,502
  • 10
  • 10
  • great answer. Working well. However, sometimes I see that the axis gets duplicated 2 times. The first plot is the plot we want, the second and the third are plots where the axes are replicated. Any idea on how to ignore them? – prashanth Nov 05 '20 at 09:18
  • @prashanth thanks for your comment. Yes you are right that we will get 1/2 duplicated items if we change 2/1 level values. Sorry I do not have a solution to this for the time being. Once I get it resolved I will reply here. – Fei Yao Nov 05 '20 at 15:15
  • Sure. Thank you. – prashanth Nov 08 '20 at 15:56