matthieu balikdjian
matthieu balikdjian

Reputation: 21

How to update automatically a plot from a dataframe that varies with a slider

I am trying to create a dashboard with panel. I have a float slider linked to a function that outputs a dataframe. Which means the dataframe varies with a slider. Then from this dataframe i create a line plot. When i "interact" the slider with the function and display the plot, only the dataframe updates but the plot doesn't refresh. I am new to python and even more to panel and widgets, so maybe i am trying to do something way too complicated that i could do easily in another way.


    import numpy as np
    import pandas as pd
    import panel as pn
    from panel.interact import interact
    
    
slider=pn.widgets.FloatSlider(name='Slider',start=0, end=70, value=0, width=400)
    
def test(V):
    x=np.linspace(0,85,850)
    y1=[]
    y=[]
    for k in x:
        y1.append(np.cos( 0.10995574287564276 - 0.00022913079470198672 * k**2 ))
    for k in y1:
        y.append((15 + V * 0.05) * k)
    
    df=pd.DataFrame(list(zip(x, y1, y)), columns = ['X' , 'Intermediate result' , 'Y'])
    
    return df    
    
inter=interact(test, V = slider)
plot=test(slider.value).hvplot(x='X', y='Y')
pn.Row(pn.Column(inter),
pn.Column(plot))

Couldn't manage to update the plot, when i just pu the slider as a parameter, it won't run and when i put slider.value, it only takes the first dataframe and never updates it

Upvotes: 0

Views: 836

Answers (3)

matthieu balikdjian
matthieu balikdjian

Reputation: 21

The solution MaximeL brought works well at first sight, but i have an error when trying to save the dashboard as a html file: here is how i proceed:

dash = pn.Row(dfi, dfi.hvplot(x='X', y='Y').output())
dash.servable()


dash.save(filename = "dashboard")

And this is what returns.

WARNING:bokeh.core.validation.check:W-1005 (FIXED_SIZING_MODE): 'fixed' sizing mode requires width and height to be set: Row(id='2590', ...)

I saw I could skip on error and it creates the panel dashboard. At that moment when I open the html file everything looks fine but the slider does not update anymore the plot. I saw on github this error but I couldn't manage to understand how to solve it or even if I can solve it. I never fixed the width or height but I assumed it was a default parameter, so when changing the sizing mode or fixing a height and a length and still I get this error. Maybe another way of saving it as an html file or displaying the dashboard would solve this issue.

Upvotes: 0

MaximeL
MaximeL

Reputation: 391

The interact API offered by Panel - and modeled on IPywidgets - is suitable for very simple cases, the docs generally steer you towards using other more flexible, yet simple to use, API. In your example in particular you want two outputs to be updated on a widget change, in which case interact isn't the best option (unless the function returns a layout consisting of the two outputs, but that's not really the spirit of interact).

Instead you can use pn.bind (from Panel) or hvplot.interactive (from hvPlot).

With pn.bind:

import hvplot.pandas
import numpy as np
import pandas as pd
import panel as pn

pn.extension()
    
slider=pn.widgets.FloatSlider(name='Slider',start=0, end=70, value=0, width=400)
    
def compute_df(V):
    x=np.linspace(0,85,850)
    y1=[]
    y=[]
    for k in x:
        y1.append(np.cos( 0.10995574287564276 - 0.00022913079470198672 * k**2 ))
    for k in y1:
        y.append((15 + V * 0.05) * k)
    
    df=pd.DataFrame(list(zip(x, y1, y)), columns = ['X' , 'Intermediate result' , 'Y'])
    
    return df    

def compute_plot(df):
    return df.hvplot(x='X', y='Y')

pn.Row(
    pn.Column(slider, pn.bind(compute_df, slider), height=400),
    pn.bind(compute_plot, pn.bind(compute_df, slider))
).servable()

With hvplot.interactive:

import hvplot.pandas
import numpy as np
import pandas as pd
import panel as pn

pn.extension()
    
slider=pn.widgets.FloatSlider(name='Slider',start=0, end=70, value=0, width=400)
    
def compute_df(V):
    x=np.linspace(0,85,850)
    y1=[]
    y=[]
    for k in x:
        y1.append(np.cos( 0.10995574287564276 - 0.00022913079470198672 * k**2 ))
    for k in y1:
        y.append((15 + V * 0.05) * k)
    
    df=pd.DataFrame(list(zip(x, y1, y)), columns = ['X' , 'Intermediate result' , 'Y'])
    
    return df    

dfi = hvplot.bind(compute_df, slider).interactive(height=400)

pn.Row(dfi, dfi.hvplot(x='X', y='Y').output()).servable()

These two examples result exactly in the same app that you can display in a notebook or serve with panel serve filename.py:

enter image description here

Upvotes: 1

Aaron Watters
Aaron Watters

Reputation: 2846

Please have a look at H5Gizmos. The following tutorial gives an example of a plot that updates based on slider values.

https://github.com/AaronWatters/H5Gizmos/blob/main/doc/Tutorials/hello_curves.md

Let me know how it goes. Thanks!

Upvotes: 0

Related Questions