Julian
Julian

Reputation: 603

ipywidgets: clear_output() has no effect. Why?

I want to provide a GUI for the user to easily remove outliers from a dataset and plot the data. Therefore, I provide input fields for the user to specify data value limits; and a button to update the plot:

import pandas as pd
import matplotlib.pyplot as plt
import ipywidgets as widgets
from IPython.display import display, clear_output

df = pd.read_csv("https://raw.githubusercontent.com/juliangermek/aia/main/treasure_data.csv", sep=";")

min_value_x = df["x"].min()
max_value_x = df["x"].max()
min_value_y = df["y"].min()
max_value_y = df["y"].max()

min_x = widgets.BoundedIntText(
    value=min_value_x,
    min=min_value_x,
    max=max_value_x,
    step=1,
    description='x lower limit:',
)
max_x = widgets.BoundedIntText(
    value=max_value_x,
    min=min_value_x,
    max=max_value_x,
    step=1,
    description='x upper limit:',
)

min_y = widgets.BoundedIntText(
    value=min_value_y,
    min=min_value_y,
    max=max_value_y,
    step=1,
    description='y lower limit:',
)
max_y = widgets.BoundedIntText(
    value=max_value_y,
    min=min_value_y,
    max=max_value_y,
    step=1,
    description='y upper limit:',
)

button = widgets.Button(description="Update image", button_style="info")
output = widgets.Output()

def on_button_clicked(b):
    with output:
        clear_output()

        is_within_x_domain = (df.x > min_x.value) & (df.x < max_x.value)
        is_within_y_domain = (df.y > min_y.value) & (df.y < max_y.value)

        df2 = df[is_within_x_domain & is_within_y_domain]
        plt.figure(figsize=(20, 4))
        plt.scatter(df2["x"], df2["y"])

button.on_click(on_button_clicked) # Run when button is clicked
on_button_clicked(button) # Run when cell is run (so show image on start)

display(min_x)
display(max_x)
display(min_y)
display(max_y)

display(button, output)

enter image description here

You should be able to run the code in this colab notebook (as long as you are signed in into a google account): https://colab.research.google.com/drive/1eblVXf8J9V0VaObig1isJAbfadfuDIbK?usp=sharing

When I click on the update button, a new plot is generated, but the old plot is not deleted although I use clear_output() in the function triggered by the button. Why is this and how can I clear the old plot before displaying the new one?

Thanks!

Upvotes: 0

Views: 1078

Answers (1)

Kamin
Kamin

Reputation: 333

As far as I know, the Output widget can not handle matplotlib plots. In ipywidgets documents:

The Output widget can capture and display stdout, stderr and rich output generated by IPython.

So you can't use this widget. Here is a workaround (which is not neat):

import pandas as pd
import matplotlib.pyplot as plt
import ipywidgets as widgets
from IPython.display import display, clear_output

df = pd.read_csv("https://raw.githubusercontent.com/juliangermek/aia/main/treasure_data.csv", sep=";")

min_value_x = df["x"].min()
max_value_x = df["x"].max()
min_value_y = df["y"].min()
max_value_y = df["y"].max()

min_x = widgets.BoundedIntText(
    value=min_value_x,
    min=min_value_x,
    max=max_value_x,
    step=1,
    description='x lower limit:',
)
max_x = widgets.BoundedIntText(
    value=max_value_x,
    min=min_value_x,
    max=max_value_x,
    step=1,
    description='x upper limit:',
)

min_y = widgets.BoundedIntText(
    value=min_value_y,
    min=min_value_y,
    max=max_value_y,
    step=1,
    description='y lower limit:',
)
max_y = widgets.BoundedIntText(
    value=max_value_y,
    min=min_value_y,
    max=max_value_y,
    step=1,
    description='y upper limit:',
)

button = widgets.Button(description="Update image", button_style="info")

def on_button_clicked(b):
    clear_output()
    display(min_x, max_x, min_y, max_y, button)
        
    is_within_x_domain = (df.x > min_x.value) & (df.x < max_x.value)
    is_within_y_domain = (df.y > min_y.value) & (df.y < max_y.value)

    df2 = df[is_within_x_domain & is_within_y_domain]
    plt.figure(figsize=(20, 4))
    plt.scatter(df2["x"], df2["y"])

button.on_click(on_button_clicked) # Run when button is clicked
on_button_clicked(button) # Run when cell is run (so show image on start)

Upvotes: 2

Related Questions