Is it possible to update a df assigned to a reactive object without recreating it ?
i am aiming at something like this :
---
df = solara.reactive(pd.DataFrame(...))
@solara.component
def Page():
(...) In a children component a function takes df as an arg, computes a new column and return the updated df. The updated df is available for other children components
---
9 Replies
Good question, I also had some trouble getting this right, so I put together this example, does that help you :
https://py.cafe/maartenbreddels/solara-mutate-dataframe
PyCafe - Solara - Mutate a dataframe, instead of a copy
PyCafe: get your daily fix of Python!
to give more context :
no df example :
factor = solara.reactive(1)
@solara.component
def Page():
population = [round( 100 *(1+0.1)**i) for i in range(0, 10)]
new = [p * factor.value for p in population]
with Column():
InputInt('Factor', value=factor)
Markdown(str(new))
Page()
but this doesn't :
factor = solara.reactive(1)
@solara.component
def Page():
df_1['new'] = df_1['population'] * factor.value
with Column():
InputInt('Factor', value=factor)
DataFrame(df_1)
Page()
by not working i mean that the df doesn't get updated while the list does
(access bloked by my company i'll have a look back home but thanks !!)
maartenbreddels
<:pull_draft:882464249065136138> [widgetti/solara] feat: detect mutation to values of reactive vars
A common source of error is mutation of values in reactive vars. The reactive var cannot notice a change in its value (e.g. a list) if the list is mutated in place.
A user can be mislead that it is working correctly, when another reactive variable triggers a rerender, teaching bad habits.
Detecting mutations in Python without using proxies can be done by making a deepcopy of the object, and comparing the reference to the deepcopy.
This comes at the cost of performance and memory usage, therefore we should enabled this by default in development mode (tests run in this mode by default), so app builders are aware of mistakes while developing.
In production mode we can disable the mutation checks and behave as before.
TODO:
- ◻️ Trigger calls to check_mutations() from several places: after an event handler (requires a change in reacton) and after a component run.
- ◻️ We probably do not want two equals function in solara/reacton, reconcile this.
- ◻️ Give an option to opt out of the mutation check per reactive var (e.g. when equals fails), or for performance reasons.
- ◻️ support reactive.get(copy=True) to always get a copy, even when _CHECK_MUTATIONS is False
- ◻️ Do we need support reactive.get(reference=True) to always get a reference, or is the opt-out enough?
Created
could you use
solara.lab.computed
?@MaartenBreddels
tried something a little bit different and it doesn't work : the df doesn't get updated dynamically
(PS: please give a working example next time, including the import, ideally by testing it on pycafe, that saves me precious time).
The problem here, is that
DataFrame
also does not see its arguments change (it's the same object).
The solution to this is: DataFrame(dff.copy(deep=False))
- which should be performant https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.copy.html
Looking back at the original issue, maybe it's better to not use the version proxy, and always make a shallow copy, wouldn't that be simpler?(my bad for the incomplete example, it tested it in a notebook (in VSCode))
thanks for the solution
I think I lack some python litteracy : why would my last example need to use a shallow copy while yours doesn't ?
solara.Dataframe (or any component for that matter) checks if the argument changed. Since it is the same object, it concludes it did not change, and will not rerender.