Watch a dataframe

Hi

I am trying to write a program to watch a change in a data frame, but it seems the depend can not catch the change.

There is a minimized example:

import param
import panel as pn
from panel.viewable import Viewer
import pandas as pd
pn.extension() 

df = pd.DataFrame(columns = ['A','B'])

class game_page(Viewer):
    
    player_info = param.DataFrame(df)
   
    def clicked(self,event):
        self.player_info.loc[len(self.player_info)] = ['new' for x in range(2)]   

    def __init__(self, **params):
        self.button = pn.widgets.Button(name = 'click')
        self.button.on_click(self.clicked)    
        self.view = pn.pane.DataFrame(self.player_info)
        
        super().__init__(**params)
        self._layout = pn.Row(self.button, self.view)

    
    def __panel__(self):
        return self._layout
    
    @param.depends('player_info', watch=True)
    def _sync_widgets(self):
        self.view.object = self.player_info
        print(f'runed')
        
    
a = game_page()

pn.Column(
    a
)

any suggestion will be grateful.

Kind regards
Victor

1 Like

Hi @CongTang

param.depends watches for changes to the player_info parameter value. I.e. if the value of player_info is replaced with a new one. It does and cannot watch for mutations of the existing value.

What you can do is to manually trigger an event via self.param.trigger('player_info') to signal that the player_info value changed.

param-trigger

import pandas as pd
import panel as pn
import param

pn.extension() 

df = pd.DataFrame(columns = ['A','B'])

class game_page(pn.viewable.Viewer):
    
    player_info = param.DataFrame(df)
   
    def clicked(self,event):
        self.player_info.loc[len(self.player_info)] = ['new' for x in range(2)]   
        self.param.trigger("player_info")

    def __init__(self, **params):
        self.button = pn.widgets.Button(name = 'click')
        self.button.on_click(self.clicked)    
        self.view = pn.pane.DataFrame(self.player_info)
        
        super().__init__(**params)
        self._layout = pn.Row(self.button, self.view)

    
    def __panel__(self):
        return self._layout
    
    @param.depends('player_info', watch=True)
    def _sync_widgets(self):
        self.view.object = self.player_info
        print(f'updated')
        
    
a = game_page()

pn.Column(
    a
).servable()

An alternative to using self.param.trigger would be to replace the value of player_info with a new dataframe. Or if performance is a concern to stream values to the Tabulator table.

4 Likes

really thanks for that marc. that works. XD

2 Likes