Unable to update data, keep creating new one instead

Hello all,

I am trying to create interactive notebook widgets with Plotly. Basically it plots a default graph when clicked, then when the user clicks the button, it updates the current graph with a new set of data.

I can plot 2 separate data, however I just cannot get it to update the same graph instead of creating a new one. I have tried various parameters such as figure.show() or figure.update() or display(f), they all plot a new graph instead of update the current one. I have attempted to update the existing object but failed to do so. I can see that someone has posted similar post in the past but received no response so I am posting the same question again.

Below is my main code with some unimportant part omitted. Any help is greatly appreciated. Thank you very much.

import plotly
import sqlite3
import ipywidgets as widgets
import plotly.graph_objects as py
from plotly.offline import iplot
plotly.offline.init_notebook_mode(connected=False)

xvalues = []
yvalues = []
data = []

button = widgets.Button(
description=‘Plot graph’,
disabled=False,
button_style=’’, # ‘success’, ‘info’, ‘warning’, ‘danger’ or ‘’
tooltip=‘Click me’,
icon=‘pencil’
)

output = widgets.Output()

display(button, output)

def on_button_clicked(b):
with output:
result = c.execute(“SELECT * FROM ‘LRP from Dマシン(5290)’ LIMIT 100 OFFSET 5000”)
loadData(result)
data = [
py.Bar(x=xvalues, y=yvalues, name=“Bar graph”),
py.Scatter(x=xvalues, y=yvalues, name=“Line graph”)
]
fig = py.Figure(data)
fig.show()

def plot(data):
data = [
py.Bar(x=xvalues, y=yvalues, name=“Bar graph”),
py.Scatter(x=xvalues, y=yvalues, name=“Line graph”)
]
layout = plotly.graph_objs.Layout(
title=“Test plot”,
legend={“x”:1, “y”:1},
xaxis={“title”:“NO”},
yaxis={“title”:“Node”},
yaxis2={“title”:“Birth Rate”, “overlaying”:“y”, “side”:“right”},
)
return data, layout

#connect to database to get data
result = c.execute(“SELECT * FROM ‘LRP from Dマシン(5290)’ LIMIT 100 OFFSET 2000”)
loadData(result)

the data

data, layout = plot(data)
fig = py.Figure(data, layout)
f2 = py.FigureWidget(fig)
f2.show()

#get new data upon clicking
button.on_click(on_button_clicked)

Hi @tonywang531, welcome to the plotly community!

just for ease of read, when you post some code please use some code fencing (see how here)

I think, the most imediate answer to your problem would be to tell the output widget to be cleared at every call like:

output = widgets.Output(clear_output=True)

but i think there are better solutions generally to update a plot. Since you are already using ipywidgets you can make use of the FigureWidget class and only update the properties you need relative to the created figure. Here I wrote a minimal example to show you how you could do it:

import plotly.graph_objects as go
import ipywidgets as widgets
import numpy as np

N = 100 # number of points
x = np.linspace(0,100,N)
y = np.zeros(N)
data = go.Scatter(x=x, y=y)
layout = dict(title='some random numbers')
fig = go.FigureWidget(data, layout)
trace = fig.data[0]

# your function to retrieve data
def get_new_data():
    # as an example return random distrib
    return np.random.randn(N)

# the button callback function
def on_button_click(b):
    trace.y = get_new_data()
    
button = widgets.Button(description='update trace')
button.on_click(on_button_click)

display(button,fig)

Hello @Alexboiboi,

Thank you very much for your response. I figured out that I can use clear_output the next day and manage to get it to work.

Of course your update trace solution is even better. This is a very elegant solution indeed, I love it! I will update the my code to this later.