Patrick Heinrich
Patrick Heinrich

Reputation: 13

Dropdown widget Python

Please bear with me. First post for me here. I am using Python, first programming language for me, for about two weeks. Now I am stuck..

I want to create a single graph with a dropdown widget. On the x-axis I want the selected year and on the y-axis I want the respective number for that year. So the year 2009 on the x-axis and 130 on the y-axis and so on.

I tried different things, basically playing around for three hours..

Maybe someone can provide me a solution? Thanks!

%matplotlib inline

import ipywidgets as widgets
from IPython.display import display
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_style("darkgrid")

dropdown = widgets.Dropdown(
    options=['2009', '2010', '2011', "2012", "2013", "2014", "2015", "2016", "2017", "2018","2019"],
    value='2009',
    description='Jahr:',
    )

def Dropdown_Menu(b):

    fig, ax = plt.subplots()
    fig.dpi = 500

    x = [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]
    y = [130, 137, 104, 147, 401, 274, 234, 770, 857, 746, 704]

    ax.plot(x, y, label = "Flugstunden pro Jahr", marker = ".")


    ax.legend()

    ax.set_title("Flugstunden")
    ax.set_xlabel("Jahr")
    ax.set_ylabel("Flugstunden")
    ax.set_facecolor((0.9,0.9,0.9))



plt.show()

dropdown.observe(Dropdown_Menu, names="value")    
display(dropdown)

Upvotes: 1

Views: 5182

Answers (1)

furas
furas

Reputation: 142651

dropdown executes Dropdown_Menu with selected value but it will not select values from list x,y. You have to do it.

For some reasons dropdown.observe() doesn't works for me so I used widgets.interact()

EDIT: it seems dropdown.observe() works only in juputer notebook but not in jupyter lab (which I use) and it would need widget Output() to work. If you will use dropdown.observe() then in Dropdown_Menu you have to use value = value.new.

%matplotlib inline

import ipywidgets as widgets
from IPython.display import display
import matplotlib.pyplot as plt

dropdown = widgets.Dropdown(
        #options=['2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019'],
        #value='2009',
        options=list(range(2009, 2020)), # integers instead of strings
        value=2009,  # integer instead of string
        description='Jahr:',
)

def Dropdown_Menu(value=2009):

    #print(type(value))
    #value = int(value)  # I dont have to convert if `Dropdown` uses integer values

    fig, ax = plt.subplots()
    fig.dpi = 150

    x = [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]
    y = [130, 137, 104, 147, 401, 274, 234, 770, 857, 746, 704]

    # get all value for `year >= value`
    #pairs = [(a,b) for a,b in zip(x, y) if a >= value] # use `==` to get only one value
    #selected_x, selected_y = zip(*pairs)

    # select values
    pos = x.index(value)
    selected_x = x[pos]
    selected_y = y[pos]

    print('x:', selected_x)
    print('y:', selected_y)

    ax.plot(selected_x, selected_y, label="Flugstunden pro Jahr", marker=".")

    ax.legend()

    ax.set_title("Flugstunden")
    ax.set_xlabel("Jahr")
    ax.set_ylabel("Flugstunden")
    ax.set_facecolor((0.9,0.9,0.9))

    #plt.show()

widgets.interact(Dropdown_Menu, value=dropdown)
#dropdown.observe(Dropdown_Menu, names="value")    
#display(dropdown)

EDIT: similar code with ipympl which gives interactive plot - so it doesn't have to replot all again and again but it can replace only line(s) (remove old line and plot new line) or it can replace only data used in line (without removig line)

%matplotlib widget 
# needs ipympl

import ipywidgets as widgets
from IPython.display import display
import matplotlib.pyplot as plt

dropdown = widgets.Dropdown(
        #options=['2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019'],
        #value='2009',
        options=list(range(2009, 2020)), # integers instead of strings
        value=2009,  # integer instead of string
        description='Jahr:',
)

fig, ax = plt.subplots()
fig.dpi = 150

x = [2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]
y = [130, 137, 104, 147, 401, 274, 234, 770, 857, 746, 704]

line, = ax.plot(x, y, label="Flugstunden pro Jahr", marker=".")

ax.legend()

ax.set_title("Flugstunden")
ax.set_xlabel("Jahr")
ax.set_ylabel("Flugstunden")
ax.set_facecolor((0.9,0.9,0.9))

#plt.show()

def on_change1(value=2009):
    """remove old line(s) and plot new line(s)"""

    #print(type(value))
    #value = int(value)   # I don't have to convert string to integer

    # get all value for `year >= value`
    #pairs = [(a,b) for a,b in zip(x, y) if a >= value] # use `==` to get only one value
    #selected_x, selected_y = zip(*pairs)

    # select data 
    pos = x.index(value)
    selected_x = x[pos]  # create `selected_x` to keep original values in `x`
    selected_y = y[pos]  # create `selected_y` to keep original values in `y`

    print('x:', selected_x)
    print('y:', selected_y)

    # remove old line(s)
    for l in ax.lines:
        l.remove()

    # plot new line(s)
    ax.plot(selected_x, selected_y, label="Flugstunden pro Jahr", marker=".")   


def on_change2(value=2009):
    """keep line, remove all data from line and use new data with the same line"""

    #print(type(value))
    #value = int(value)   # I don't have to convert string to integer

    # get all value for `year >= value`
    #pairs = [(a,b) for a,b in zip(x, y) if a >= value] # use `==` to get only one value
    #selected_x, selected_y = zip(*pairs)

    # select data 
    pos = x.index(value)
    selected_x = x[pos]  # create `selected_x` to keep original values in `x`
    selected_y = y[pos]  # create `selected_y` to keep original values in `y`

    print('x:', selected_x)
    print('y:', selected_y)

    line.set_xdata(selected_x)
    line.set_ydata(selected_y)
    #fig.canvas.draw()

widgets.interact(on_change1, value=dropdown) 
#widgets.interact(on_change2, value=dropdown) 

Upvotes: 1

Related Questions