holoviz / param

Param: Make your Python code clearer and more reliable by declaring Parameters
https://param.holoviz.org
BSD 3-Clause "New" or "Revised" License
433 stars 74 forks source link

TypeError: 'rx' object does not support item assignment #965

Open ahuang11 opened 2 months ago

ahuang11 commented 2 months ago

Originally from https://discourse.holoviz.org/t/normalizing-stock-market-data-with-reactive-dataframe/7515


I am trying to normalize stock market data of an reactive DataFrame. I am getting an error and need a bit of help.

This is the minimal, reproducible example:

import pandas as pd
import panel as pn

# Create DateTimeIndex
dates = pd.date_range(start='2023-01-01', end='2023-01-10', freq='D')

# Price data
prices = [101.5, 98.2, 103.7, 100.4, 104.6, 97.8, 106.3, 99.5, 105.2, 108.0]

# Create DataFrame
df = pd.DataFrame(data={'Price': prices}, index=dates)

In a normal DataFrame I would do this to normalize the stock price:

# First Index
first_index = df.index[0]

# Normalize Price
df["Price_normalized"] = df["Price"] / df.loc[first_index, 'Price']

print(df)

However, in my case I am filtering the DataFrame with a DateRangeSlider. Because of this the first_index, on which i normalize, changes. It should always be the first price of the filtered DataFrame "rdf". The basic pandas method does not work and I get an error.

rdf=pn.rx(df)

# First Index
first_index = rdf.index[0]

# Normalize Price
rdf["Price_normalized"] = rdf["Price"] / rdf.loc[first_index, 'Price']

I am getting the TypeError:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[33], line 7
      4 first_index = rdf.index[0]
      6 # Normalize Price
----> 7 rdf["Price_normalized"] = rdf["Price"] / rdf.loc[first_index, 'Price']

TypeError: 'rx' object does not support item assignment
philippjfr commented 2 months ago

Can you use assign?

rdf.assign(Price_normalized=rdf["Price"] / rdf.loc[first_index, 'Price']})
ahuang11 commented 2 months ago

Yeah I think that works.

import pandas as pd
import panel as pn
pn.extension()

# Create DateTimeIndex
dates = pd.date_range(start='2023-01-01', end='2023-01-10', freq='D')

# Price data
prices = [101.5, 98.2, 103.7, 100.4, 104.6, 97.8, 106.3, 99.5, 105.2, 108.0]

# Create DataFrame
df = pd.DataFrame(data={'Price': prices, 'Dates': dates})
rdf = pn.rx(df)
first_index = rdf.index[0]
rdf.assign(Price_normalized=rdf["Price"] / rdf.loc[first_index, 'Price'])
philippjfr commented 2 months ago

Method chaining should generally be preferred over assignment, but we might still consider __setitem__.