Understanding .rx() behavior on mutable objects

Hi all, I was wondering if I could get help understanding some of the behavior of using rx.

import param
import panel as pn

URL = 'https://datasets.holoviz.org/penguins/v1/penguins.csv'
df = pd.read_csv(URL)
dfrx = param.rx(df)

# this works
year_rx = pn.rx(2007)
dfrx_filt = dfrx[dfrx["year"] == year_rx]
pn.pane.DataFrame( dfrx_filt ) #works

year_rx.rx.value = 2008 # this works, automatically updates the above dfrx_filt pane


# don't understand the below behavior
dfrx.rx.value = df.iloc[:10,:] # this updates the above pane
dfrx.rx.value.loc["island"] = "GILLIGAN" # DOESN'T WORK. this doesn't drive the behavior, and the above pane doesn't change
dfrx.rx.value.loc[:,"test"] = "TEST" # DOESN'T WORK. this doesn't drive the behavior, and the above pane doesn't change

So my question is trying to understand when ____.rx.value drives value updates, and when it doesn’t.

I run into similar problems working with pn.rx({…}) and pn.rx([…]), so I’m guessing the problem lies with nuances of a mutable item vs. immutable item (e.g. int and strs).

Context: I want a dfrx that I perform more complicated actions than simply filtering, and was trying to figure out what expressions can and can’t be used to drive reactive behavior.

Thanks!

I haven’t really used rx yet, but I guess it’s not an RX issue per se, but basically panel not seeing any .value change while watching it for changes.

Issue looks similar to what you get if you use basic panel and Parameter in param.parameterized classes.

Eg. A param.DataFrame() displayed with a pn.widgets.Tabulator.
Only a swap of the complete df updates the tabulator, not any manual changes within the df. Same with lists etc …

I’m not sure if my impression of rx is right, but it seems to mainly allow you to use param.parameter/param.parameterized watcher and other magic incl panel behind the scene parameter/widget updates without having to define param.parameterized classes.

So, had some time to briefly play with your example, kinda confirms my understanding.

dfrx.rx.value = df.iloc[:10,:] # this updates the above pane

→ does change UI because you are assigning a new value to dfrx.rx.value (basically replacing the value)

dfrx.rx.value.loc[:,"island"] = "GILLIGAN" # DOESN'T WORK. this doesn't drive the behavior, and the above pane doesn't change

→ doesn’t update the UI, because you’re not assigning a new dfrx.rx.value, but just retrieving the DF from .value and doing some work on that object (I assume PARAM/RX wouldn’t have a clue if it EVEN updates the DF at all or is just reading it)

If you modify your example to actually create a new DF and assign it to the dfrx.rx.value, UI gets updated:

dfrx.rx.value = dfrx.assign(island='GILLIAN')

Of course if you don’t assign the resulting new DF back into dfrx.rx.value, UI doesn’t get updated either.

1 Like