1

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)
6
  • what do you use jupyter to run it ? Commented Apr 27, 2020 at 22:19
  • i didn't run it but in Dropdown_Menu you always use the same values in x, y so it will always draw the same plot. You have to filter values to get something different. Commented Apr 27, 2020 at 22:22
  • what is the problem? Do you get error, or it gives wrong plot or it doesn't display anything? Commented Apr 27, 2020 at 22:49
  • I use jupyter to run it. Commented Apr 27, 2020 at 23:10
  • I cannot figure out how to assign only one y value to x. When I run it I get a graph with all the years in x and their respective y values. The Dropdown-Menu is not properly linked to those x and y values. My goal is to tap the Dropdown-Menu and select one year then the graph pops up and shows me the selected year and the respective y value. Commented Apr 27, 2020 at 23:13

1 Answer 1

1

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)

EDIT (2025):

As @Wayne suggested in comment below: currently can be used %matplotlib ipympl and it explocitly shows that it needs to install ipympl (so it doesn't need comment # needs ipympl in code).

And as @Wayne said: "%matplotlib widget is a leftover from a legacy time when JupyterLab and Jupyter Noebook didn't use the same things."

And link to basic example in ipympl doc (also from comment).

%matplotlib ipympl    # explictly shows that it needs `ipympl`

# %matplotlib widget  # still work as legacy but doesn't show that it needs `ipympl`
# 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) 
Sign up to request clarification or add additional context in comments.

1 Comment

@Wayne I added your information in answer. Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.